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;
}
Related
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?
Within a Portable Class Library, I have 2 classes:
The parent
public class Parent
{
public string inherited;
public static string inheritedStatic;
}
And the child the derives from it
public class Child : Parent
{
public static string mine;
}
The problem is that I cannot get the inherited static field named "inheritedState", I just get the non-static ("inherited").
This is the code that I'm running:
class Program
{
static void Main(string[] args)
{
var childFields = typeof(Child).GetTypeInfo().GetRuntimeFields();
foreach (var fieldInfo in childFields)
{
Console.WriteLine(fieldInfo);
}
}
}
What should I do to get the inherited static field?
Thanks!
You could use:
public static FieldInfo[] DeclaredFields(TypeInfo type)
{
var fields = new List<FieldInfo>();
while (type != null)
{
fields.AddRange(type.DeclaredFields);
Type type2 = type.BaseType;
type = type2 != null ? type2.GetTypeInfo() : null;
}
return fields.ToArray();
}
For PCL library, and tested for my:
public static IEnumerable<FieldInfo> DeclaredFields(Type type)
{
var fields = new List<FieldInfo>();
while (type != null)
{
fields.AddRange(type.GetRuntimeFields());
type = type.GetTypeInfo().BaseType;
}
return fields;
}
I have created an architecture in my C# code which does exactly what I want, but seems it would be very difficult to maintain in the long-run and am hoping there's a design pattern / better architecture I could be pointed towards.
I have created an object Test which, again, does exactly what I need perfectly which has the following structure:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
private Lazy<object> _test1;
public object Test1 { get { return _test1.Value; } }
private Lazy<object> _test2;
public object Test2 { get { return _test2.Value; } }
public Test()
{
_test1 = new Lazy<object>(() => MethodDictionary["Test1"](this), true);
_test2 = new Lazy<object>(() => MethodDictionary["Test2"](this), true);
}
}
What this allows me to do is, at run-time to assign a dictionary of functions to my Test object and the 2 properties Test1 & Test2 will use the functions loaded into it to return values.
The implementation looking somewhat as follows:
class Program
{
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1.ToString());
Console.WriteLine(x.Test2.ToString());
Console.ReadKey();
}
private static object TestMethod1(Test t)
{ return t.Var1 + t.Var2; }
private static object TestMethod2(Test t)
{ return t.Var1 - t.Var2; }
}
And it works great and has proven very efficient for large sets of Test objects.
My challenge is that if I ever want to add in a new method to my Test class, I need to add in the:
private Lazy<object> _myNewMethod;
public object MyNewMethod { get { return _myNewMethod.Value; } }
Update the constuctor with the key to look for in the dictionary
And, although that is pretty simple, I'd love to have a 1-line add-in (maybe some form of custom object) or have the properties read directly form the dictionary without any need for defining them at all.
Any ideas? ANY help would be great!!!
Thanks!!!
One of the ways in which you could achieve your desired behavior, is to use something that resembles a miniature IoC framework for field injection, tuned to your specific use case.
To make things easier, allow less typing in your concrete classes and make things type-safe, we introduce the LazyField type:
public class LazyField<T>
{
private static readonly Lazy<T> Default = new Lazy<T>();
private readonly Lazy<T> _lazy;
public LazyField() : this(Default) { }
public LazyField(Lazy<T> lazy)
{
_lazy = lazy;
}
public override string ToString()
{
return _lazy.Value.ToString();
}
public static implicit operator T(LazyField<T> instance)
{
return instance._lazy.Value;
}
}
Furthermore, we define an abstract base class, that ensures that these fields will be created at construction time:
public abstract class AbstractLazyFieldHolder
{
protected AbstractLazyFieldHolder()
{
LazyFields.BuildUp(this); // ensures fields are populated.
}
}
Skipping for a moment how this is achieved (explained further below), this allows the following way of defining your Test class:
public class Test : AbstractLazyFieldHolder
{
public double Var1;
public double Var2;
public readonly LazyField<double> Test1;
public readonly LazyField<double> Test2;
}
Note that these fields are immutable, initialized in the constructor. Now, for your usage example, the below snippet shows the "new way" of doing this:
LazyFields.Configure<Test>()
// We can use a type-safe lambda
.SetProvider(x => x.Test1, inst => inst.Var1 + inst.Var2)
// Or the field name.
.SetProvider("Test2", TestMethod2);
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1);
double test2Val = x.Test2; // type-safe conversion
Console.WriteLine(test2Val);
// Output:
// 50
// -10
The class below provides the services that support the configuration and injection of these field value.
public static class LazyFields
{
private static readonly ConcurrentDictionary<Type, IBuildUp> _registry = new ConcurrentDictionary<Type,IBuildUp>();
public interface IConfigureType<T> where T : class
{
IConfigureType<T> SetProvider<FT>(string fieldName, Func<T, FT> provider);
IConfigureType<T> SetProvider<F, FT>(Expression<Func<T, F>> fieldExpression, Func<T, FT> provider) where F : LazyField<FT>;
}
public static void BuildUp(object instance)
{
System.Diagnostics.Debug.Assert(instance != null);
var builder = _registry.GetOrAdd(instance.GetType(), BuildInitializer);
builder.BuildUp(instance);
}
public static IConfigureType<T> Configure<T>() where T : class
{
return (IConfigureType<T>)_registry.GetOrAdd(typeof(T), BuildInitializer);
}
private interface IBuildUp
{
void BuildUp(object instance);
}
private class TypeCfg<T> : IBuildUp, IConfigureType<T> where T : class
{
private readonly List<FieldInfo> _fields;
private readonly Dictionary<string, Action<T>> _initializers;
public TypeCfg()
{
_fields = typeof(T)
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Where(IsLazyField)
.ToList();
_initializers = _fields.ToDictionary(x => x.Name, BuildDefaultSetter);
}
public IConfigureType<T> SetProvider<FT>(string fieldName, Func<T,FT> provider)
{
var pi = _fields.First(x => x.Name == fieldName);
_initializers[fieldName] = BuildSetter<FT>(pi, provider);
return this;
}
public IConfigureType<T> SetProvider<F,FT>(Expression<Func<T,F>> fieldExpression, Func<T,FT> provider)
where F : LazyField<FT>
{
return SetProvider((fieldExpression.Body as MemberExpression).Member.Name, provider);
}
public void BuildUp(object instance)
{
var typedInstance = (T)instance;
foreach (var initializer in _initializers.Values)
initializer(typedInstance);
}
private bool IsLazyField(FieldInfo fi)
{
return fi.FieldType.IsGenericType && fi.FieldType.GetGenericTypeDefinition() == typeof(LazyField<>);
}
private Action<T> BuildDefaultSetter(FieldInfo fi)
{
var itemType = fi.FieldType.GetGenericArguments()[0];
var defValue = Activator.CreateInstance(typeof(LazyField<>).MakeGenericType(itemType));
return (inst) => fi.SetValue(inst, defValue);
}
private Action<T> BuildSetter<FT>(FieldInfo fi, Func<T, FT> provider)
{
return (inst) => fi.SetValue(inst, new LazyField<FT>(new Lazy<FT>(() => provider(inst))));
}
}
private static IBuildUp BuildInitializer(Type targetType)
{
return (IBuildUp)Activator.CreateInstance(typeof(TypeCfg<>).MakeGenericType(targetType));
}
}
Look at library https://github.com/ekonbenefits/impromptu-interface.
With it and using DynamicObject i wrote sample code that shows how to simplify adding new methods:
public class Methods
{
public Methods()
{
MethodDictionary = new Dictionary<string, Func<ITest, object>>();
LazyObjects = new Dictionary<string, Lazy<object>>();
}
public Dictionary<string, Func<ITest, object>> MethodDictionary { get; private set; }
public Dictionary<string, Lazy<object>> LazyObjects { get; private set; }
}
public class Proxy : DynamicObject
{
Methods _methods;
public Proxy()
{
_methods = new Methods();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _methods.LazyObjects[binder.Name].Value;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_methods.MethodDictionary[binder.Name] = (Func<ITest, object>)value;
_methods.LazyObjects[binder.Name] = new Lazy<object>(() => _methods.MethodDictionary[binder.Name](this.ActLike<ITest>()), true);
return true;
}
}
//now you can add new methods by add single method to interface
public interface ITest
{
object Test1 { get; set; }
object Test2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new Proxy().ActLike<ITest>();
x.Test1 = new Func<ITest, object>((y) => "Test1");
x.Test2 = new Func<ITest, object>((y) => "Test2");
Console.WriteLine(x.Test1);
Console.WriteLine(x.Test2);
}
}
I don't know what you are trying to do, but I think you can use a simpler approach like this:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
}
Calling the function is simple:
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(Test.MethodDictionary["Test1"](x).ToString());
Console.WriteLine(Test.MethodDictionary["Test2"](x).ToString());
Console.ReadKey();
}
Lets say I have a generic class:
class Foo {
// protected Type t;
// public void SetT(string strval) {
// ((Foo<t>)this).Set(strval);
// }
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
if (this is Foo<float>) {
this.val = float.Parse(strval);
} else if (this is Foo<int>) {
this.val = int.Parse(strval);
}
}
}
Now I create an object and put it in an ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>);
And then I forget the type of Foo<>. Now, how do I Set? I tried the obvious candidates:
(Foo)a[0].Set("5.0");
(Foo<a[0].GetType()>)a[0].Set("5.0");
but those failed.
Is there a way I can call that Set method without explicitly knowing the type of Foo<>?
If not, can I somehow save type of Foo into Foo.t, and then uncomment and use Foo.SetT?
Ah, generics. Very nice tool if you know how to use them :-)
Regards,
dijxtra
One way is to make your generic Foo class implement an interface:
interface IFoo {
void Set(string strval);
}
class Foo<T> : IFoo {
private T val;
public void Set(string strval) {
...
}
}
Then you can cast to IFoo and call Set():
((IFoo)a[0]).Set("5.0");
There's absolutely no reason to be using generics here. Generics are intended to be used when the type of operations you will be performing are generic. In other words, they are independent of the type(s) on which they are performed. You are doing the opposite: the operation will be different depending on the types.
Given that, you should remove the generic parameter, make Set() and Foo abstract, and derive appropriate classes to handle the different types:
abstract class Foo
{
public abstract void Set(string value);
}
class FooDouble : Foo
{
double val;
public override void Set(string value)
{
this.val = double.Parse(value);
}
}
// Etc.
Then, you should be storing your Foos in a List<T>:
List<Foo> fooList = new List<Foo>();
fooList.Add(new FooDouble());
Later, you can say this:
fooList[0].Set("5.0");
And it will just work! No need to remember!
You want to override the implementation of Set in the derived classes.
class Foo {
public virtual void Set(string val);
}
class Foo<T> : Foo {
public override void Set(string val);
}
In addition to what Jimmy pointed out for your base class, you could use a generic collection instead of an ArrayList and make use of a type converter:
public interface IFoo
{
void Set(string value);
}
public class Foo<T> : IFoo
{
private T val;
public void Set(string value)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if(typeConverter.CanConvertFrom(typeof(string)))
{
val = (T)typeConverter.ConvertFromString(value);
}
else
{
throw new InvalidOperationException();
}
}
}
The above will work with either your ArrayList:
ArrayList a = new ArrayList();
a.Append(new Foo<float>());
((IFoo)a[0]).Set("123.4");
Or with a typed collection:
List<IFoo> list = new List<IFoo>();
list.Add(new Foo<float>());
list[0].Set("123.4");
As an added bonus, you don't need to have an if statement in your Set method and try to account for all possible types.
If you want to know the type parameter that was used in you generic, use the GetGenericArguments method.
class Foo<T> {
int input_as_int;
float input_as_float;
public void Set(string strval) {
if (this.GetType().GetGenericArguments().First() == typeof(float)) {
this.input_as_float = float.Parse(strval);
} else if (this.GetType().GetGenericArguments().First() == typeof(int)) {
this.input_as_int = int.Parse(strval);
}
// Else .. throw an exception? return default value? return 0? what makes sense to your application
}
or alternately if you could by pass the Interface entirely and pass the input string in the constructor.
public class Foo<T>
{
public Foo (string input)
{
var typeConverter = TypeDescriptor.GetConverter(typeof(T));
if (typeConverter.CanConvertFrom(typeof(string)))
{
Value = (T)typeConverter.ConvertFromString(input);
}
else
{
throw new InvalidOperationException();
}
}
public T Value { get; set;
}
}
then you can just use it like so.
var test = new List<int> Foo ("3");
using System;
using System.Collections;
using System.Collections.Generic;
class Foo {
}
class Foo<T> : Foo {
private T val;
public void Set(string strval) {
var _type = typeof(T);
val = (T)(_type.InvokeMember("Parse", System.Reflection.BindingFlags.InvokeMethod, null, null, new Object[] { strval }));
}
override public string ToString(){
return String.Format("{0}", val);
}
}
class Sample {
static void Main(string[] args){
ArrayList a = new ArrayList();
a.Add(new Foo<float>());
a.Add(new Foo<int>());
dynamic ax = a[0];
ax.Set("5.5");
ax = a[1];
ax.Set("55");
//EDIT
//But I may have to set the float value to Foo <int> If you forgot
// ((Foo<float>)a[0]).Set("5.5");
// ((Foo<int>)a[1]).Set("55");
Console.WriteLine("{0},{1}", a[0], a[1]);
}
}
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"