I would like to know, for the following code example, how I can assign values to myClass Obj, using Type.InvokeMember or with field.SetValue. The field name and value are represented as strings.
class myClass
{
public string obj1;
public string obj2;
}
class myClass2
{
public myClass obj = new myClass();
}
class Program
{
static void Main(string[] args)
{
Type type = Type.GetType("ConsoleApp2.myClass2");
object classObj = Activator.CreateInstance(type);
FieldInfo fi = type.GetField("obj");
fi.SetValue(??????);
type.InvokeMember("obj", BindingFlags.SetField, null, classObj , ?????);
}
}
It's very simple in your sample you should be able to do something like:
fi.SetValue(classObj, new myClass());
so in your case:
class myClass
{
public string obj1;
public string obj2;
}
class myClass2
{
public myClass obj = new myClass();
}
class Program
{
static void Main(string[] args)
{
Type type2 = Type.GetType("ConsoleApp1.myClass");
object classObj2 = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(classObj2 ,"some str1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(classObj2 ,"some str2");
Type type = Type.GetType("ConsoleApp1.myClass2");
object classObj = Activator.CreateInstance(type);
FieldInfo fi = type.GetField("obj");
fi.SetValue(classObj,classObj2);
}
}
This seems simple
fi.SetValue(classObj, "new value");
as stated in documentation. Did this not work for you?
Related
class myClass1
{
public string obj1;
public string obj2;
}
class myClass2
{
public myClass1[] fArray = new myClass1[1];
public string str;
}
class Program
{
static void Main(string[] args)
{
string mytype = "ConsoleApp3.myClass2";
Type type = Type.GetType(mytype);
object myObj = Activator.CreateInstance(type);
FieldInfo fi = type.GetField("fArray");
Type type2 = fi.FieldType.GetElementType();
object newObj;
IList list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(fi.GetValue(myObj).GetType().GetElementType()));
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
{
newObj = Activator.CreateInstance(type2);
FieldInfo fi2 = type2.GetField("obj1");
fi2.SetValue(newObj, "some txt1");
FieldInfo fi3 = type2.GetField("obj2");
fi3.SetValue(newObj, "some txt2");
list.Add(newObj);
}
fi.SetValue(myObj, list.Cast<myClass1>().ToArray());
The Code above is working fine. In my usecase "myClass1" is not know at the compile time. I am receiving the type of myClass1 as a string at runtime.
How can I cast a list to array of type myClass1 using reflection?
fi.SetValue(myObj, list.Cast<???>().ToArray());
You can make generic methods too:
Let's create a local variable for the element type so we can reuse it.
var elementType = fi.GetValue(myObj).GetType().GetElementType();
...
Get the cast method and the array method from the linq enumerable class.
var castMethod = typeof(System.Linq.Enumerable).GetMethod("Cast").MakeGenericMethod(elementType);
var arrayMethod = typeof(System.Linq.Enumerable).GetMethod("ToArray").MakeGenericMethod(elementType);
Call the methods with null as the first argument for static methods.
var casted = castMethod.Invoke(null, new[] { list });
var array = arrayMethod.Invoke(null, new[] { casted });
fi.SetValue(myObj, array);
There may be a smarter way of doing this, but this might get you started.
Type.GetType and Type.MakeArrayType comes to your aid.
You can do:
Type t = Type.GetType("myString");
or
Type arrayT = Type.GetType("myString").MakeArrayType() ;
In your example, GetType would be enough, but it's good to know about MakeArrayType as well.
From Java I've used the below code to invoke method. Pass the Instance of the class where the method is and then execute.
Context context; //Assuming the passed Instance is initialized here
Class c = Class.forName(context.getClass().getName()); //Get the class name including it's package and initialized here
Method m = c.getMethod("thisMethod", String.class, String.class); //Initialize the Method name and it's parameter type
Object t = c.newInstance();
m.invoke(t,"data1", "data2"); //Invoke the method with 2 string
I would like to convert the above code in C#. I've tried to search and I found this link and it's confused me on how can I use the instance I've passed. so far I have the below code in C#.
class Program{
static InvokerClass ic;
private static Program programInstance = new Program();
static void Main(string[] args){
ic = new InvokerClass(programInstance);
ic.StartInvokeExample("Hello","World!");
}
//Call this method later
public static void thisMethod(String data1, String data2) {
Console.WriteLine("DATA1=>" + data1 + ", DATA2=>"+data2);
}
}
class InvokerClass{
private Object objInstance;
public InvokerClass(Object obj){
this.objInstance = obj; //Get the passed Instance and use this to determine the Class Name
}
//Do invoking here
public void StartInvokeExample(String data1, String data2){
Type t = Type.GetType("? ? ?"); //I wanted to use the `objInstance` to determine the Class name
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}
From InvokerClass I would like to used the objInstance to initialize the Class name but I don't know how. And so far I don't know if I'm doing it in proper way.
This should do it for you:
class InvokerClass
{
private Object objInstance;
public InvokerClass(Object obj)
{
if (obj == null) throw new ArgumentNullException("obj must not be null");
this.objInstance = obj; //Get the passed Instance and use this to determine the Class Name
}
//Do invoking here
public void StartInvokeExample(String data1, String data2)
{
Type t = objInstance.GetType();
object classObject = Activator.CreateInstance(t);
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}
Note: you won´t need to get the constructor, simply use Activator.CreateInstance. Also take care to verify your passed object is not null to avoid a NullReferenceÈxception when trying to call objInstance.GetType().
You can pass in the object instance, but I would probably change it to use a generic instead. Although you are passing in the program object, doing it this way would provide a little more flexibility, because you don't need a an instantiated object to create a new one. You could also create an overload and get both. In your example, I would change the methods to static since you don't need an instantiated object in your example.
class Program
{
private static Program programInstance = new Program();
static void Main(string[] args)
{
InvokerClass.StartInvokeExample<Program>("Hello", "World!");
}
public static void thisMethod(String data1, String data2)
{
Console.WriteLine("DATA1=>" + data1 + ", DATA2=>" + data2);
}
}
class static InvokerClass
{
//Do invoking here
public void StartInvokeExample<T>(String data1, String data2)
where T : new()
{
Type t = typeof(T);
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
public static StartInvokeExample
(Type t, String data1, String data2)
{
ConstructorInfo cons = t.GetConstructor(Type.EmptyTypes);
object classObject = cons.Invoke(new object[] { });
MethodInfo m = t.GetMethod("thisMethod");
m.Invoke(classObject, new object[] { data1, data2 });
}
}
I have a bunch of classes that inherit from a single class. I'm using reflections to access the classes, since the ones that will be accessed will change in runtime.
But I am having some trouble when trying to invoke a method declared at superclass.
Here is my parent class:
public class ParentClass {
public ParentClass (Type type) {
}
public string method0String () {
return string;
}
public void method1Void (string) {
}
}
Here is my child class:
public class ChildClass : ParentClass {
public ParentClass () : base(typeof(ChildClass)) {
}
}
Here is the abstract class code where I cast the methods:
Type childType = Type.GetType(className[i]);
ConstructorInfo childConstructor = childType.GetConstructor(new Type[0]);
object childObject = null;
childObject = childConstructor.Invoke(childObject, new object[0]);
MethodInfo parentMethod0String = childType.GetMethod("method0String");
MethodInfo parentMethod1Void = childType.GetMethod("method1Void");
parentMethod1Void.Invoke(childObject, new object[]{argString});
object finalString = parentMethod0String.Invoke(childObject, new object[0]);
The MethodInfos are always null, which causes this error when I try to invoke them:
System.NullReferenceException: Object reference not set to an instance of an object
I haven't found anyway around this.
Basically, I just need to invoke a super method using the child as the dynamic object. How can I achieve this?
#Edit
After #nvoigt answer, my code looks like this:
Type childType = Type.GetType(className[i]);
object childObject = Activator.CreateInstance(childType);
Type parentType = Type.GetType("ParentClass");
MethodInfo parentMethod0String = parentType.GetMethod("method0String");
MethodInfo parentMethod1Void = parentType.GetMethod("method1Void");
parentMethod1Void.Invoke(childObject, new object[]{argString});
object finalString = parentMethod0String.Invoke(childObject, new object[0]);
And the error is a little different:
System.Reflection.TargetException: Object does not match target type.
You can do it this way:
namespace StackOverFlowTest
{
using System;
class BaseClass
{
public int BaseClassMethod(int x)
{
return x * x;
}
}
class DerivedClass : BaseClass
{
}
class Program
{
static void Main()
{
var derivedType = typeof(DerivedClass);
var baseType = typeof(BaseClass);
var method = baseType.GetMethod("BaseClassMethod");
var derivedInstance = Activator.CreateInstance(derivedType);
var result = method.Invoke(derivedInstance, new object[] { 42 });
Console.WriteLine(result);
Console.ReadLine();
}
}
}
HI All,
I need to access the class SomeClass which is declared has a private field in the Wrapper class, using Reflection so far i have been able to get private field members . How do i cast it back to its original type so that i could access it properties and other members.
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
FieldInfo[] infos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var item in infos)
{
}
}
}
internal class SomeClass
{
public int Number { get; set; }
}
internal class Wrapper
{
private SomeClass _tempSomeObj;
public SomeClass SOmeProperty
{
get
{
return _tempSomeObj;
}
set
{
_tempSomeObj = value;
}
}
}
I dont know if i understand the question correct. You want the type of the private field (backing field)??
Then you could check the FieldType property of the FieldInfo....
like this:
internal class Program
{
#region Methods
private static void Main(string[] args)
{
var wrap = new Wrapper { SOmeProperty = new SomeClass { Number = 007 } };
Type type = wrap.GetType();
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var fieldInfo in fieldInfos)
{
if (fieldInfo.FieldType == typeof(SomeClass))
{
Console.WriteLine("Yap!");
}
}
}
#endregion
}
internal class SomeClass
{
#region Properties
public int Number { get; set; }
#endregion
}
internal class Wrapper
{
#region Properties
public SomeClass SOmeProperty { get; set; }
#endregion
}
Use PropertyInfo instead:
internal class Program
{
private static void Main(string[] args)
{
Wrapper wrap = new Wrapper
{
SOmeProperty = new SomeClass
{
Number = 007
}
};
Type type = wrap.GetType();
PropertyInfo info = type.GetProperty("SOmeProperty", BindingFlags.NonPublic | BindingFlags.Instance);
SomeClass value = (SomeClass)info.GetValue(wrap, null);
// use `value` variable here
}
}
I'm still a little fuzzy about what your're trying to do, but you can always GetType() on any object and get its actual run time type and query that for properties field of some other type for example
public void ListPropertiesOfType( object targetObject, Type propertyType ) {
foreach( var foundProperty in targetObject.GetType( ).GetProperties( ).Where( p => p.PropertyType == propertyType ) ) {
Console.WriteLine( "Name: {0}, Value: {1}", foundProperty.Name, foundProperty.GetValue( targetObject, null ) );
}
}
ListPropertiesOfType(new Wrapper(), typeof(SomeClass))
ListPropertiesOfType(new Wrapper(), typeof(SomeOtherClass))
If you want to pass in instances of Someclass and SomeClass that is also fine, just use GetType() on the instances to get the type that you can then use to find properties of that type as illustrated above. this works the same way regardless if you make the method generic and pass in "T" or if its non-generic and you pass in "object"
Is there any way to get FieldInfo of a field in a function that is going to assign a value to that variable?
See my example:
class SomeClass{
MyType myObject = SomeOtherClass.MyFunction();
}
class SomeOtherClass{
public static MyType MyFunction(){
//Get FieldInfo about myObject here
}
}
Background:
What I want to do is to be able to set an attribute on "myObject" which specifies that the object should be cached in "MyFunction".
Sorry Herber, I tried responding in a comment but this was to large to work as a comment:
In the case you mentioned in response to my last reply, does this work for you?
class Program
{
static void Main(string[] args)
{
SomeClass sc = new SomeClass();
}
}
class SomeClass
{
public MyType myObject;
public SomeClass()
{
SomeOtherClass.MyFunction(this);
}
}
static class SomeOtherClass
{
public static void MyFunction(SomeClass sClass)
{
sClass.myObject = new MyType() { Name = "Test1" };
FieldInfo[] fInfo = sClass.myObject.GetType().GetFields();
Console.WriteLine(fInfo[0].GetValue(sClass.myObject));
}
}
class MyType
{
public string Name;
}
This is completely impossible.
When the function is called, it has no awareness of what you're going to do with the result.
There isn't any way you can do it using the assignment operator. The MyFunction function requires a reference to the myObject object to be able to determine the field info.
Your best bet is to either check before the assignment or to pass myObject into MyFunction
Not sure if this is what your're after: But you could try using the an "out" parameter so as the method you are calling has knowledge of target of the assignment? like so:
class SomeClass
{
MyType myObject;
public SomeClass()
{
SomeOtherClass.MyFunction(out myObject);
}
}
static class SomeOtherClass
{
public static void MyFunction(out MyType mType)
{
mType = new MyType();
FieldInfo[] fInfo = mType.GetType().GetFields();
}
}
class MyType
{
string Name;
}
Hope that helps :¬)
OK one last stab before I call it a night...
class Program
{
static void Main(string[] args)
{
SomeClass sc = new SomeClass();
}
}
[AttributeUsage(AttributeTargets.Field)]
public class MyAttribute : System.Attribute
{
public readonly bool Foo;
public MyAttribute(bool foo)
{
Foo = foo;
}
}
class SomeClass
{
[MyAttribute(true)]
public MyType myObject;
[MyAttribute(true)]
public int myInt;
public bool myBool;
public SomeClass()
{
SomeOtherClass.MyFunction(this);
}
}
static class SomeOtherClass
{
public static void MyFunction(SomeClass sClass)
{
sClass.myObject = new MyType() { Name = "Test1"};
foreach(FieldInfo finfo in GetFeilds(sClass))
Console.WriteLine(finfo.GetValue(sClass));
}
public static IEnumerable<FieldInfo> GetFeilds(SomeClass sClass)
{
foreach (FieldInfo field in typeof(SomeClass).GetFields())
{
foreach (Attribute attr in field.GetCustomAttributes(true))
{
if (field.GetCustomAttributes(typeof(MyAttribute), true)!= null && ((MyAttribute)attr).Foo)
yield return field;
}
}
}
}
class MyType
{
public string Name;
}