My Problem
I have a Problem which i can not solve my self. I dont want to use so much code, because i have multiple Classes which extend another class (in my case its called "Data").
I have a log file, where each Data Group is beginning with a specific Group Name, for example "MitarbeiterSet". The abstract Data-Class is used to prefent to much code, where I implemented variables like "String[] data" (for the data beeing parsed from the log file e.g. < 101 4 3 6 3 30 80 2 0 0 1 300 >) or "static String parseInduction", which is used to determin, if this Class is the right one to create Objects from.
I have another Class, called ParseMonitor, which creates the StreamReader to parse the log-file. So if the right Class is found, i induct the setDataArray(StreamReader sr) function from the right Class, to parse the Data Array. (At this point i have to tell you, that i need those different Classes, because i need to upload them to a sql server specificly.)
This static function creates an object of it self and uses the parseLine(String line) Function to fill the object with data from the given line.
WHAT I NEED.
I want to call the static function of any class, just by having the name of this class. So i dont have to use that much code and be able to add more classes.
Later on i want to call every class and use the uploadToServer() to Upload it to the server.
Is this possible?
Since your static method is creating an instance of its class anyway, I suggest a different approach:
Create an interface that all classes that contain ParseLine can implement. (Change out the return type for the correct one):
public interface IParseLine
{
string ParseLine(string line);
}
Have all of the classes that contain ParseLine() implement IParseLine.
Create an instance of the class, cast it to an IParseLine, and execute the method:
IParseLine pl = Activator.CreateInstance(Type.GetType(className)) as IParseLine;
if (pl != null)
{
string parsedString = pl.ParseLine(line);
// ...
}
Edit From comments:
I want to create a while loop, which can be stated as followed:
while{!sr.EndofStream){ line = sr.ReadLine(); for(int i = 0; i <
classNames.length; i++){ if(line.Contains(classNames[i].MYINDICATOR){
CALL classNames[i] STATIC METHOD TO PARSE THE FOLLOWING LINES AND
CREATE DATA Objects of its Class } }
I didn't test this, but you can change the code to something like this (caching the reflection required to get MYINDICATOR):
IList<KeyValuePair<string, Type>> typeIndicators = classNames.Select(x => {
Type t = Type.GetType(x);
string indicator = (string)t.GetField("MYINDICATOR", BindingFlags.Public | BindingFlags.Static).GetValue(null);
return new KeyValuePair(indicator, t);
});
while (!sr.EndOfStream)
{
line = sr.ReadLine();
foreach (var types in typeIndicators)
{
if (line.Contains(types.Key))
{
IParseLine pl = Activator.CreateInstance(types.Value) as IParseLine;
if (pl != null)
{
string parsedString = pl.ParseLine(line);
}
}
}
}
I want to call the static function of any class, just by having the name of this class.
Well, you can use Type.GetType(className) to get a Type (note that the name needs to at least be fully qualified including the namespace, and may also need the assembly name depending on your exact scenario), then Type.GetMethod to get a MethodInfo. Finally, call MethodBase.Invoke to invoke the method.
If you could use typeof(Foo) instead of using a string, it would make the code simpler and more robust.
(Side-note: if your methods are really called parseLine, parseInduction, setDataArray etc, you should consider renaming them to follow .NET naming conventions :)
I think I see where you're coming from. In this simple exmaple below, I have a static class with a method in it (nothing amazing about that).
public static class MyStaticClass
{
public static DateTime GetTime()
{
return DateTime.Now;
}
}
If I want to invoke that method using reflection, I can just use the following code, but it does assume that the MyStaticClass class is available via a reference or inthe same project etc.
MethodInfo method = typeof(MyStaticClass).GetMethod("GetTime");
object result = method.Invoke(null, null);
if (result is DateTime)
{
Console.WriteLine(((DateTime)result).ToLongTimeString());
}
What you seem ot be asking for is a moethod of doing this when you don't have a reference to the class. In which case, try something like this:
MethodInfo method = Type.GetType("PocStaticReflect.MyStaticClass, PocStaticReflect, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null").GetMethod("GetTime");
object result = method.Invoke(null, null);
if (result is DateTime)
{
Console.WriteLine(((DateTime)result).ToLongTimeString());
}
Notice the fully qualified class name!
If you get that working, then you can simply loop though your class names and call the method you desire. Obviously, you'll probably want more error checking and more detail in the GetMethod() calls, but this shlud give you the gist of it. I've done something similar before looping though assemblies in a folder to pickup plug-ins for an application. That time, each of the classes implemented an interface to make them easier to locate, which may be helpful path to follow.
Or try this:
private static object GetResultFromStaticMethodClass(string qualifiedClassName, string method)
{
Type StaticClass = Type.GetType(qualifiedClassName);
MethodInfo methodInfo = StaticClass.GetMethod(method);
object result = methodInfo.Invoke(null, null);
return result;
}
Use:
object result = GetResultFromStaticMethodClass(
"Utilities.StringHelper,DaProject",
"ToList"
);
This call the static method ToList in the StringHelper class, in the Utilities namespace, in the DaProject project (same assembly and project name).
If you need parameters, add them in the second parameter in the methodInfo.Invoke(null, null) call
Related
For example, consider a utility class SerializableList:
public class SerializableList : List<ISerializable>
{
public T Add<T>(T item) where T : ISerializable
{
base.Add(item);
return item;
}
public T Add<T>(Func<T> factory) where T : ISerializable
{
var item = factory();
base.Add(item);
return item;
}
}
Usually I'd use it like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(new Class1());
var item2 = serializableList.Add(new Class2());
I could also have used it via factoring, like this:
var serializableList = new SerializableList();
var item1 = serializableList.Add(() => new Class1());
var item2 = serializableList.Add(() => new Class2());
The second approach appears to be a preferred usage pattern, as I've been lately noticing on SO. Is it really so (and why, if yes) or is it just a matter of taste?
Given your example, the factory method is silly. Unless the callee requires the ability to control the point of instantiation, instantiate multiple instances, or lazy evaluation, it's just useless overhead.
The compiler will not be able to optimize out delegate creation.
To reference the examples of using the factory syntax that you gave in comments on the question. Both examples are trying (albeit poorly) to provide guaranteed cleanup of the instances.
If you consider a using statement:
using (var x = new Something()) { }
The naive implementation would be:
var x = new Something();
try
{
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
The problem with this code is that it is possible for an exception to occur after the assignment of x, but before the try block is entered. If this happens, x will not be properly disposed, because the finally block will not execute. To deal with this, the code for a using statement will actually be something more like:
Something x = null;
try
{
x = new Something();
}
finally
{
if ((x != null) && (x is IDisposable))
((IDisposable)x).Dispose();
}
Both of the examples that you reference using factory parameters are attempting to deal with this same issue. Passing a factory allows for the instance to be instantiated within the guarded block. Passing the instance directly allows for the possibility of something to go wrong along the way and not have Dispose() called.
In those cases, passing the factory parameter makes sense.
Caching
In the example you have provided it does not make sense as others have pointed out. Instead I will give you another example,
public class MyClass{
public MyClass(string file){
// load a huge file
// do lots of computing...
// then store results...
}
}
private ConcurrentDictionary<string,MyClass> Cache = new ....
public MyClass GetCachedItem(string key){
return Cache.GetOrAdd(key, k => new MyClass(key));
}
In above example, let's say we are loading a big file and we are calculating something and we are interested in end result of that calculation. To speedup my access, when I try to load files through Cache, Cache will return me cached entry if it has it, only when cache does not find the item, it will call the Factory method, and create new instance of MyClass.
So you are reading files many times, but you are only creating instance of class that holds data just once. This pattern is only useful for caching purpose.
But if you are not caching, and every iteration requires to call new operator, then it makes no sense to use factory pattern at all.
Alternate Error Object or Error Logging
For some reason, if creation fails, List can create an error object, for example,
T defaultObject = ....
public T Add<T>(Func<T> factory) where T : ISerializable
{
T item;
try{
item = factory();
}catch(ex){
Log(ex);
item = defaultObject;
}
base.Add(item);
return item;
}
In this example, you can monitor factory if it generates an exception while creating new object, and when that happens, you Log the error, and return something else and keep some default value in list. I don't know what will be practical use of this, but Error Logging sounds better candidate here.
No, there's no general preference of passing the factory instead of the value. However, in very particular situations, you will prefer to pass the factory method instead of the value.
Think about it:
What's the difference between passing the parameter as a value, or
passing it as a factory method (e.g. using Func<T>)?
Answer is simple: order of execution.
In the first case, you need to pass the value, so you must obtain it before calling the target method.
In the second case, you can postpone the value creation/calculation/obtaining till it's needed by the target method.
Why would you want to postpone the value creation/calculation/obtaining? obvious things come to mind:
Processor-intensive or memory-intensive creation of the value, that you want to happen only in case the value is really needed (on-demand). This is Lazy loading then.
If the value creation depends on parameters that are accessible by the target method but not from outside of it. So, you would pass Func<T, T> instead of Func<T>.
The question compares methods with different purposes. The second one should be named CreateAndAdd<T>(Func<T> factory).
So depending what functionality is required, should be used one or another method.
I'm a bit confused atm and i dont think it could be this hard as then i must be doing something wrong. What i am trying to do now for the past 2 days is to access a method inside an object that is stored in an List and i just cant get at it. In my mind it should just be to get the object back to its originated type and invoke the method but i just cant do it.
I been reading alot about Type, Generics and reflection but it cant get anyting to work so i am obviusly doing it all wrong and i need help finding the light!
Heres the latest code i have tried
Object customer = Hotel.Main.Manager.GetMainList(x);
Type frsttype = customer.GetType();
MethodInfo method = frsttype.GetMethod("GetCustomerSpecificData");
MethodInfo generic = method.MakeGenericMethod(frsttype);
String str = generic.Invoke(method);
What i am trying to reach is this method inside the object:
public override string GetCustomerSpecificData()
{
string strout = string.Format("{0,-5}{1,26}{2,28}{3,28}\a", ID, Name, Age, Gender);
string strInfo = Extra;
strout += (string.IsNullOrEmpty(strInfo) ? string.Empty : strInfo);
if (m_specialoffer)
{
strout += string.Format("\nSpecial Offer");
}
if (IsRegularCustomer)
{
strout += (IsDangerus ? "\nIs a regular customer " : "\nIs not a regular customer.");
}
strout += Environment.NewLine + PaymentInfo();
strout += (m_CarPark ? "\nHas car parked in garage." : "\nDoes not have car parked in garage.");
return strout;
}
I hope someone can point me in the correct direction as i dont think i am getting anywhere with this one :/
Any help and hints will be greatly appreciated!!! All will be upvoted for replies!
Regards
There a few things here that you need to do, firstly lets look at the codeyou posted
First question you need t ask youself is Do I need to use reflection, can I instead use interfaces or return a type that I know?
Do you have control of the GetMainList(x)? If so cant you change it so it returns something more useful other then a object?
Object customer = Hotel.Main.Manager.GetMainList(x);
Can you cast to anything?
Secondly your target method is no a generic method so the line below is not going to work.
MethodInfo generic = method.MakeGenericMethod(frsttype);
You are also invoking the method incorrectly you Invoke has two arguments the first one is the target object you wish to invoke the method against and the parameters you can pass into it.
Invoke(object obj, object[] parameters)
To invoke you method you need to the following.
Object customer = Hotel.Main.Manager.GetMainList(x);
Type frsttype = customer.GetType();
MethodInfo method = frsttype.GetMethod("GetCustomerSpecificData");
String str = method.Invoke(customer, null) as string;
There is some great questions and community wikis on stackoverflow and of course there is many tutorials and example in the MSDN library.
A nice tutorial for reflection in .net can be found below.
Reflection in C# Tutorial
i mean you can easy invoke it :
Type myType =customer.GetType();
MethodInfo method = typeof(customer).GetMethod("GetCustomerSpecificData");
MethodInfo generic = method.MakeGenericMethod(myType);
var res= generic.Invoke(this, null);
Closest to what you currently have this could work without relying on reflection.
Object customer = Hotel.Main.Manager.GetMainList(x);
string result="";
var custObj = customer as Customer;
if (custObj !=null)
{
result = custObj.GetCustomerSpecificData();
}
var specialcustObj = customer as SpecialCustomer;
if (specialcustObj !=null)
{
result = specialcustObj.GetCustomerSpecificData();
}
/* etc */
Or, If you can change the implementation of the different types in the List have an interface (or alternative an (abstract) base class.
/* alternatively name it ISpecificData if you want adhere common used standards */
public interface SpecificData
{
string GetCustomerSpecificData();
}
and for your Customer and other classes that can be in the list :
public class Customer:SpecificData
{
/* rest of implemementastion stays the same */
}
Your code to Get a customer would go like this, and will work for every object in the list that implemented the interface.
Object customer = Hotel.Main.Manager.GetMainList(x);
string result="";
var interfaceObj = customer as SpecificData;
if (interfaceObj != null)
{
result = interfaceObj.GetCustomerSpecificData();
}
When you know that only a specific interface will be in the list you can use the generic list to only hold object for that specific type:
mainlist = new List<SpecificData>();
and you can adapt GetMainList to only return the interface SpecificData
The problem I am having is that I would like to call a method from a string. Here is what I am doing:
Building My List of Strings (Methods) there are three different checkboxList objects in my UI
private List<string> MyTest = new List<string>();
private void AddSelectedMethods()
{
foreach(XName item in BaseTestList.CheckedItems)
{
MyTests.Add(item.ToString());
}
foreach (XName item in AdminTestList.CheckedItems)
{
MyTests.Add(item.ToString());
}
foreach (XName item in SubscriberTestList.CheckedItems)
{
MyTests.Add(item.ToString());
}
}
Here is the Caller. If I take out the Reflections call and reference the method directly everything works but I don't want to get into crating a huge list of if else statements.
private void StartSiteTest(object sender, DoWorkEventArgs e)
{
if (!BackWorker1.CancellationPending)
{
if (SiteToTest == "estatesales.vintagesoftware.local" || SiteToTest == "localhost")
{
es = new EstateSaleTests(site, Sites.First(i => i.SiteUrl == SiteToTest), BasePath, SiteToTest, UseCurrentCompanies);
foreach (string test in MyTests)
{
// <<<!!!!!!!! ------ The next line returns null ------ !!!!!!!>>>
MethodInfo thisMethod = es.GetType().GetMethod(test);
thisMethod.Invoke(es, null);
}
}
}
}
Any help on what I am doing wrong would be greatly appreciated.
!!!----- EDIT -----!!!
I'm an idiot. I had the class set to the list of strings but I forgot to rename my Methods Sorry about that. Yes the Methods were public and they are accessible I just have to rename them to the correct names now.
The call you use seems pretty acceptable, imo.
The thing is that GetType().GetMethod() is able to recover only public methods.
See this MSDN link.
In order to access methods with different acessors use this GetMethod(string, BindingFlags) overload.
Hope this helps.
I notice this has already been well-answered, but the following might still be of use.
Sometimes it is hard to find the method using reflection. You're currently just searching for public instance methods only. What I usually do when finding the method through reflection appears rather hard, is using GetMethods() with different binding flags and check by hand whether the expected methods are there.
Note that when you specify binding flags, you must also specify BindingFlags.InvokeMethod | BindingFlags.Instance. In addition, consider the following:
If the method is an instance method, use BindingFlags.Static
If you don't know whether you have the caption right ("CalcRoot" is different than "calcRoot") than use BindingFlags.IgnoreCase
If you think the method is protected, internal, private or protected internal, use BindingFlags.NonPublic
If you are not sure whether you use a derived type, use BindingFlags.FlattenHierarchy
If you are uncertain whether what you are looking for is a property, field or method, use GetMembers instead.
You can combine all flags with | to search for everything. With a little bit trial and error you'll eventually find the set of binding params that you need.
I need to create the ability to drill through an objects properties like two or three deep. For instance, class A has a property reference to class B, which I need to access class C. What is the best way to do this: straight reflection, or maybe using the TypeDescriptor, or something else?
Thanks.
It's not too hard to write. I put a few classes together to deal with this so I could serialize properties of a WinForm. Take a look at this class and the related classes.
http://csharptest.net/browse/src/Library/Reflection/PropertySerializer.cs
If you know the path in a static context (ie the path is always the same) and the properties are accessible (internal or public) you can use dynamic
[Test]
public void Foo()
{
var a = new A
{
B = new B
{
C = new C
{
Name = "hello"
}
}
};
DoReflection(a);
}
private void DoReflection(dynamic value)
{
string message = value.B.C.Name;
Debug.WriteLine(message);
}
I you wanna write you own serialization code for whatever reason, you'll be using reflection.
What you do is that you write a recursive method of serlizating a type. You then apply this as you see fit to get the result.
var type = myObjectOfSomeType.GetType();
// now depending on what you want to store
// I'll save all public properties
var properties = type.GetProperties(); // get all public properties
foreach(var p in properties)
{
var value = p.GetValue(myObjectOfSomeType, null);
Writevalue(p.Name, value);
}
The implementation of WriteValue have to recognize the built in types and treat them accordingly, that's typical things like string, char, integer, double, DateTime etc.
If it encounters a sequence or collection you need to write out many values.
If it encounters a non trivial type you'll apply this recursive pattern again.
The end result is a recursive algorithm that traverses your object model and writes out values as it encounters types that I know how to serialize.
However, I do recommend looking into WCF, not for building services, but for serialization. It shipped as part of the .NET 3.0 framework with a new assembly System.Runtime.Serilization and in general is very capable when dealing with serialization and data annotations.
i have a class with a static public property called "Info".
via reflection i want to get this properties value, so i call:
PropertyInfo pi myType.GetProperty("Info");
string info = (string) pi.GetValue(null, null);
this works fine as long as the property is of type string. but actually my property is of type IPluginInfo and a PluginInfo type (implementing IPluginInfo) is instatiated and returned in the Info properties get accessor, like this:
public static IPluginInfo PluginInfo
{
get
{
IPluginInfo Info = new PluginInfo();
Info.Name = "PluginName";
Info.Version = "PluginVersion";
return Info;
}
}
like this when i call:
IPluginInfo info = pi.GetValue(null, null) as IPluginInfo;
info is always null, whiel PropertyInfo pi is still valid. am i missing something obvious here?
Could you create a short but complete program that demonstrates the problem?
Given that you're talking about plugins, my guess is that you've got the problem of having IPluginInfo defined in two different assemblies. See if this article helps at all.
The easiest way to verify it is to call pi.GetValue and store the result in an object variable first, then do the cast or "as" in another line. That way you can break the debugger and look at the return value before it's lost.
My first guess would be that you have re-declared the IPluginInfo interface. All .NET types are scoped by their assembly; if you have the same class file in 2 assemblies, you have 2 different interfaces that happen to have the same name.
ok, thanks for all the answers.
i indeed already had the plugininterface in a separate .dll but had placed this .dll in the pluginhosts directory as well as in the directory with all the plugins.
Um, first of all I'd implement that property a little differently:
private static PluginInfo _PluginInfo = null;
public static IPluginInfo PluginInfo
{
get
{
if (_PluginInfo == null)
{
_PluginInfo = new PluginInfo();
_PluginInfo.Name = "PluginName";
_PluginInfo.Version = "PluginVersion";
}
return _PluginInfo;
}
}
Note that this needs a little more work because it isn't threadsafe, but hopefully you get the idea: build it one time rather than repeatedly.
I'll stop here now, since it looks like two others already finished the rest of my answer while putting together the first part.
In C#, AS returns null if the value does not match the type.
If you write:
object info = pi.GetValue(null, null);
Console.WriteLine(info.GetType().ToString());
what type do you receive?