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;
}
Related
I'd like to create a List from all of the constants in the nested classes.
public struct SomePair
{
public string Name, Value;
public SomePair(string name, string value)
{
Name = name;
Value = value;
}
}
private static MemberInfo[] GetClasses() => typeof(MainFoo).GetMembers(BindingFlags.Public);
private static List<Type> GetClassTypes() => GetClasses().Select(c=>c.GetType()).ToList();
public static class MainFoo
{
// The return value should contain the information about the SomeConstant's from both Errors and Foo.
public static List<LocalizationPair> Dump()
{
List<SomePair> Dump = new List<SomePair>();
var classes = GetClassTypes();
foreach (Type cls in classes)
{
var constants = cls.GetFields(BindingFlags.Public); // <<< Is always empty...
foreach (FieldInfo constant in constants)
{
Dump.Add(new SomePair(
$"{cls.Name}.{constant.Name}",
constant.GetValue(cls).ToString()
));
}
}
return Dump;
}
public static class Errors
{
public constant string SomeConstant = "a";
}
public static class Foo
{
public constant string SomeConstant = "a";
}
}
I'm able to get a list of all classes and a list of all class-types but once I try to use GetMember() on those, it returns nothing.
Use GetNestedTypes() instead with the correct BindingFlags for public constants:
var nestedTypes = typeof(MainFoo).GetNestedTypes(BindingFlags.Public);
foreach (Type type in nestedTypes)
{
FieldInfo[] constants = type.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
// <do stuff here>
}
I have a method that iterates the fields of a class, returning their values as a CSV. I need a way to give classes access to this method in a generic fashion.
For some reason, Statics must derive from object or you get a compile error. In this case, deriving from a different base class does increase code re-useability for me. Is there another way to accomplish my goal?
I believe the only choice I have is to make my static class an instance class.
//a data container used for Mocking in inversion of control
public class FieldContainer : ReflectionHelper<FieldContainer>
{
public static string Field1 = "Some Data";
public static string Field2 = "Persons Name";
public static string Field3 = "3030 Plane Ave.";
}
public class ReflectionHelper<T>
{
public static string ToCSV()
{
StringBuilder fieldCollector = new StringBuilder();
Type type = typeof(T);
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo f in fields)
{
fieldCollector.Append(f.GetValue(null) + ",");
}
return fieldCollector.ToString();
}
}
Your code is perfectly valid (at least technically). Your class FieldContainer is not a static class and therefore it can derive from ReflectionHelper<T>.
However, you normally would not implement the method ToCSV in a base class, because it can basically work on ANY class. Because you want to work on static members, an extension method isn't the best way either. The simplest and cleanest way to do it, will be to have a static helper class that implements this method:
public static class ReflectionHelper
{
public static string ToCSV<T>()
{
StringBuilder fieldCollector = new StringBuilder();
Type type = typeof(T);
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo f in fields)
{
fieldCollector.Append(f.GetValue(null) + ",");
}
return fieldCollector.ToString();
}
}
You can use it like this:
var csv = ReflectionHelper.ToCSV<FieldContainer>();
However, I fail to see, why you would want to implement something like that at all. It doesn't seem to make too much sense.
You could form it as an extension method, as such:
public static class ReflectionHelperExtensions
{
public static string ToCSV<T>(this T instance)
{
var type = instance.GetType();
var fields = type.GetFields();
var fieldCollector = new StringBuilder();
foreach (FieldInfo f in fields)
{
fieldCollector.Append(f.GetValue(null) + ",");
}
return fieldCollector.ToString();
}
}
This way, your field container classes don't need to derive from any given type, as this applies to all derivatives of object.
Have you concidered using an extension method?
public static class ReflectionExtensions
{
public static string ToCSV(this object input)
{
StringBuilder fieldCollector = new StringBuilder();
Type type = input.GetType();
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo f in fields)
{
fieldCollector.Append(f.GetValue(null) + ",");
}
return fieldCollector.ToString();
}
}
Then you could simply call the following on any object:
FieldContainer c = new FieldContainer();
string result = c.ToCSV();
It's fine if you have the class as an instanced type.
public abstract class ReflectionHelper<T>
{
protected ReflectionHelper()
{ }
public static string ToCsv(string delimiter = ",")
{
var fieldCollector = new StringBuilder();
var type = typeof(T);
var fields = type.GetFields();
foreach (var f in fields)
{
fieldCollector.Append(f.GetValue(null) + delimiter);
}
return fieldCollector.ToString();
}
}
public class Something : ReflectionHelper<Something>
{
protected Something() : base()
{
}
public static string Field1 = "Some Data";
public static string Field2 = "Persons Name";
public static string Field3 = "3030 Plane Ave.";
}
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"
I wrote a class that allows a derivate to specify which of its properties can be lazy loaded. The code is:
public abstract class SelfHydratingEntity<T> : DynamicObject where T : class {
private readonly Dictionary<string, LoadableBackingField> fields;
public SelfHydratingEntity(T original) {
this.Original = original;
this.fields = this.GetBackingFields().ToDictionary(f => f.Name);
}
public T Original { get; private set; }
protected virtual IEnumerable<LoadableBackingField> GetBackingFields() {
yield break;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
result = field.GetValue();
return true;
} else {
var getter = PropertyAccessor.GetGetter(this.Original.GetType(), binder.Name);
result = getter(this.Original);
return true;
}
}
public override bool TrySetMember(SetMemberBinder binder, object value) {
LoadableBackingField field;
if (this.fields.TryGetValue(binder.Name, out field)) {
field.SetValue(value);
return true;
} else {
var setter = PropertyAccessor.GetSetter(this.Original.GetType(), binder.Name);
setter(this.Original, value);
return true;
}
}
}
And a derivate class:
public class SelfHydratingPerson : SelfHydratingEntity<IPerson> {
private readonly IDataRepository dataRepository;
public SelfHydratingDerivate(IDataRepository dataRepository, IPerson person)
: base(person) {
this.dataRepository = dataRepository
}
protected override IEnumerable<LoadableBackingField> GetBackingFields() {
yield return new LoadableBackingField("Address", () => this.dataRepository.Addresses.Get(this.Original.AddressID));
}
}
This works perfectly fine for getting and settings property values, but I get a either a RuntimeBinderException when I implicitly cast or an InvalidCastException with an explicitly cast SelfHydratingEntity back to T.
I know that you can override the DynamicObject.TryConvert method, but I'm wondering what exactly to put in this method. I've read a lot about duck typing today, and have tried out several libraries, but none of them work for this particular scenario. All of the libraries I've tried today generate a wrapper class using Reflection.Emit that makes calls to "get_" and "set_" methods and naturally use reflection to find these methods on the wrapped instance. SelfHydratingEntity of course doesn't have the "get_" and "set_" methods defined.
So, I'm wondering if this kind of thing is even possible. Is there any way to cast an instance of SelfHydratingEntity to T? I'm looking for something like this:
var original = GetOriginalPerson();
dynamic person = new SelfHydratingPerson(new DataRepository(), original);
string name = person.Name; // Gets property value on original
var address = person.Address; // Gets property value using LoadableBackingField registration
var iPerson = (IPerson)person;
- or -
var iPerson = DuckType.As<IPerson>(person);
Have you seen this Duck Typing project. It looks pretty good. I have just found a great example from Mauricio. It uses the Windsor Castle dynamic proxy to intercept method calls
Using the code from Mauricio the following code works like a dream
class Program
{
static void Main(string[] args)
{
dynamic person = new { Name = "Peter" };
var p = DuckType.As<IPerson>(person);
Console.WriteLine(p.Name);
}
}
public interface IPerson
{
string Name { get; set; }
}
public static class DuckType
{
private static readonly ProxyGenerator generator = new ProxyGenerator();
public static T As<T>(object o)
{
return generator.CreateInterfaceProxyWithoutTarget<T>(new DuckTypingInterceptor(o));
}
}
public class DuckTypingInterceptor : IInterceptor
{
private readonly object target;
public DuckTypingInterceptor(object target)
{
this.target = target;
}
public void Intercept(IInvocation invocation)
{
var methods = target.GetType().GetMethods()
.Where(m => m.Name == invocation.Method.Name)
.Where(m => m.GetParameters().Length == invocation.Arguments.Length)
.ToList();
if (methods.Count > 1)
throw new ApplicationException(string.Format("Ambiguous method match for '{0}'", invocation.Method.Name));
if (methods.Count == 0)
throw new ApplicationException(string.Format("No method '{0}' found", invocation.Method.Name));
var method = methods[0];
if (invocation.GenericArguments != null && invocation.GenericArguments.Length > 0)
method = method.MakeGenericMethod(invocation.GenericArguments);
invocation.ReturnValue = method.Invoke(target, invocation.Arguments);
}
}
impromptu-interface
https://github.com/ekonbenefits/impromptu-interface
Can static cast interfaces onto objects derived from DynamicObject.
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;
}