|
Will you only instantiate each class once? Some form of Singleton may be beneficial here.
Second mug of coffee coming up...
|
|
|
|
|
Nope. Each of the derived classes will have multiple static members, each of which are instances of the derived class, being added to the dictionary in the base class.
|
|
|
|
|
Hmmm... well, that doesn't really make it any more difficult...
|
|
|
|
|
Hi,
Someone has to take the initiative for a collection to be populated.
if you don't plan on touching the specialized translators before calling on AllTranslators, the only solution I can see is by having reflection code in the static initializer of Translator, so it can go out and search for translators, feeding them to AllTranslators.
[EDIT]
You should not make allTranslators public, instead have a public AllTranslators property; you then can postpone the reflective search till the property is used for the first time.
[/EDIT]
|
|
|
|
|
Luc Pattyn wrote: Someone has to take the initiative for a collection to be populated
Therein lies the rub. .net likes to be lazy in its instantiation, and even allows the developer to make it even lazier.
What we need here is to make .net be pro-active.
Luc Pattyn wrote: reflection code in the static initializer of Translator
I don't even think that would do it.
It appears that, in theory, this should even work for plug-in assemblies that get loaded after the manager class.
I certainly haven't found a way to tell the runtime to initialize the class immediately upon load rather than waiting for some code to reference it.
|
|
|
|
|
PIEBALDconsult wrote: I certainly haven't found a way to tell the runtime to initialize the class immediately upon load
there isn't AFAIK. And I never felt a need for it either. The OP seems like a request for a regular plug-in scheme.
|
|
|
|
|
Luc Pattyn wrote: a regular plug-in scheme
Seems very similar, yes. But something will have to register the plug-in before the client can request it.
|
|
|
|
|
So I tried that approach out, with a method that I called on first access of the dictionary,
static private void initialize()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(Translator)))
{
type.InvokeMember("Initialize", BindingFlags.InvokeMethod, null, null, null);
}
}
}
}
It is pretty heavy handed, but it has one big benefit, over say tying into the assembly AssemblyLoad event, there is nothing extra for the Translator client to do. It also still has a problem, the derived class assembly still has to be loaded at some point. But I see no way around that.
FYI, I also tried a assembly attribute similar to the one http://joshsmithonwpf.wordpress.com/2010/04/07/assembly-level-initialization-at-design-time/ but alas the attribute is only called if reflection is used on the assembly
So right now this is the best solution I have.
Thanks,
|
|
|
|
|
thugthug wrote: the assembly still has to be loaded at some point
Two common approaches are:
1. provide a GUI Control (Menu, ComboBox) listing all assemblies from a specific directory, and allow the user to choose which one(s) to load.
2. load all assemblies from a specific directory.
And there is a middle way: if all you need is a specific translator, you might have a class and method Translators.LoadOne(string name) that first checks if it has been loaded before, and if not, goes to the specific directory, does a filename search, and loads the matching assembly.
|
|
|
|
|
That's more-or-less what I have working at the moment -- except with a generic manager class using parameter-less constructors.
You could probably add a method to the manager that will load specified assemblies:
manager.Load ( "plugins\\*.dll" ) ;
I also defined an interface and am using type.IsAssignableFrom rather than type.IsSubclassOf .
|
|
|
|
|
One last change that I threw in was to combine a couple efforts,
1) Using reflection.
2) Using assembly attributes.
First add a custom attribute to the assembly info for FrenchTranslator that looks like this:
[assembly: Bootstrapper()]
[AttributeUsage(AttributeTargets.Assembly)]
class BootstrapperAttribute : Attribute
{
public BootstrapperAttribute()
{
Translators.FrenchTranslator.Initialize();
}
}
So if this attribute ever did load, it would call the the method Translators.FrenchTranslator.Initialize(), and the static instance would come into being. Problem is no one is every going to look for this attribute and it will not ever be loaded!
To get the attribute loaded, I added an initialize method in the translator class looks that looks like this and is called on first access to the dictionary.
static private void initialize()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
assembly.GetCustomAttributes(true);
}
}
So someone accesses the dictionary for the first time, the initialize method causes the all the assemblies with the specified attribute to tell there contained classes to initialize, and poof the static members exist.
The benefit of this over the previous method is that now I don't have to check every single type that has been loaded in.
Much Thanks to all.
James
|
|
|
|
|
Veddy intewesting...
Though it still only knows about types in assemblies that have been loaded.
I've been looking at the plug-in angle of this and have it working to some extent.
It still requires a parameter-less constructor, rather than an Initialize method.
I am considering using attributes to tell the manager how to instantiate the class.
I suggest you take Keith's advice and separate the translator classes from the manager class.
|
|
|
|
|
Considering:
0) We have pretty much determined that what you were originally asking about is currently impossible.
1) You need to enumerate the types in the loaded assemblies (and/or develop an all-out plug-in system).
I question whether or not the static instances and Initialize methods are required at this point -- I think that they were simply failed attempts at trying to get it work the way you thought it might.
Certainly, the way I'm doing it doesn't use either.
Aren't your static instances merely duplicates of what's in the Dictionary?
And is there any code in the Initialize methods?
Can you remove them without harming the process? (Perhaps alter your Attribute to refer to something else?)
(I'm also not so thrilled about the Attribute.)
|
|
|
|
|
PIEBALDconsult wrote: Aren't your static instances merely duplicates of what's in the Dictionary?
Undoubtedly.
PIEBALDconsult wrote: And is there any code in the Initialize methods?
Nope.
Can you remove them without harming the process? (Perhaps alter your Attribute to refer to something else?)
(I'm also not so thrilled about the Attribute.)
Afraid not.
To be more clear:
Actually the static instances are the primary method of accessing the data in most (99%) cases , this look-up-by-name feature is only needed for a small sub-set of clients. The problem being that when the clients do look-up-by-name there was no guarantee that the class had ever been accessed, and the static instances initialized. The dictionary serves two roles, first as the look-up-by-name feature and second maintaining uniqueness in the names (this is very important in the actually application).
|
|
|
|
|
If you're not usually looking them up by name, then why require that the names be unique?
I recommend having the lookup as the normal/only access method.
But I suppose it may be too late.
|
|
|
|
|
Hi there,
I'm currently trying to serialize a wsdl.exe generated object
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.1432")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace="http://myNamespace/")]
public partial class marketDataEventV1 {
using the following lines of code:
marketDataEventV1 mdEvent = CreateMarketDataEventV1();
XmlSerializer ser = new XmlSerializer(typeof(marketDataEventV1));
StringBuilder sb = new StringBuilder();
ser.Serialize(new StringWriter(sb), mdEvent);
Now, having a look to sb.ToString() shows, that the result (string) does not contain the namespace declaration.
I wonder now, how to get the serializer taking account for the namespace?!
Thanks in advance!
|
|
|
|
|
Take a look at this[^]
Use the XmlSerializerNamespaces to add your namespace and pass it to the ser.Serialize overload method.
Tarakeshwar Reddy
There are two kinds of people, those who do the work and those who take the credit. Try to be in the first group; there is less competition there. - Indira Gandhi
|
|
|
|
|
Thanks, I've already noticed XmlSerializerNamespaces , but this way, I need to code which namespace belongs to which object. But that's exactly what the [System.Xml.Serialization.XmlTypeAttribute(Namespace="http://myNamespace/")] -attribute says.
So how to tell the serializer to have a look for these attributes? I expected that as a default..
|
|
|
|
|
May be XmlRootAttribute[^] is what you need to use.
Tarakeshwar Reddy
There are two kinds of people, those who do the work and those who take the credit. Try to be in the first group; there is less competition there. - Indira Gandhi
|
|
|
|
|
That works, thank you.
However, I did not expect to need to change the generated code.
|
|
|
|
|
|
Did you make sure you have access to the machines you're trying to connect to - does the user which runs your app exist on the remote machine with the same password?
If not, then I too get the "Could not connect to Remote Computer" message. Otherwise it works just fine.
|
|
|
|
|
Hi,
Thanks for the reply.
please look at the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Diagnostics;
using System.ServiceProcess;
using System.IO;
using System.Collections;
namespace ListNetworkComputers
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}
private void frmMain_Load(object sender, EventArgs e)
{
try
{
NetworkBrowser nb = new NetworkBrowser();
foreach (string pc in nb.getNetworkComputers())
{
cmbNetworkComputers.Items.Add(pc);
}
}
catch (Exception ex)
{
throw ex;
}
}
private void cmbNetworkComputers_SelectedIndexChanged(object sender, EventArgs e)
{
string nm = cmbNetworkComputers.Text.ToString();
IPHostEntry ip = Dns.GetHostEntry(nm);
string hostip = ip.AddressList[0].ToString();
Process[] ipByName = Process.GetProcesses(nm);
foreach (Process p in ipByName)
{
cmbIPList.Items.Add(p.ProcessName.ToString());
}
}
}
}
as i am not able to attach my project here so I am getting error at Process[] ipByName = Process.GetProcesses(nm);
My application is present On Server and remaining are clients.
So i want to get all the processes of clients
Thanks
Ajay Kulkarni.
|
|
|
|
|
Did you actually read Callas' response?
You should never use standby on an elephant. It always crashes when you lift the ears. - Mark Wallace
C/C++ (I dont see a huge difference between them, and the 'benefits' of C++ are questionable, who needs inheritance when you have copy and paste) - fat_boy
|
|
|
|
|
Guess not, but then again I didn't "supply codez.."
|
|
|
|