C#, reflection, inheritence and static fields? - c#

I have a family of classes that inherit from an abstract superclass, which is implemented by two concrete classes:
public abstract class AbstractFoo
{
protected static string fooName = "Reset me!";
public static string GetName()
{
return fooName;
}
}
The subclasses are then constructed like
public class BarFoo : AbstractFoo
{
static BarFoo()
{
fooName = "Pretty Name For BarFoo";
}
}
and so forth.
I want to get a list of all the AbstractFoo implementations' pretty names so the user can decide which implementation to use.
My reflection code looks like
Type fooType = typeof(AbstractFoo);
List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));
foreach (Type thisType in fooTypes)
{
MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
string name = (string) method.Invoke (null, null);
// add to the list, anyhow names.Add (name);
}
I end up with method.Invoke always returning "Rename Me" rather than the individual names.
I'm pretty sure I'm doing something silly here, but I'm not quite sure what.

You have two problems.
First, your static field really isn't going to be doing what you want it to. There's one static field, in AbstractFoo - there isn't a separate BarFoo.fooName static field. So if you have a bunch of subclasses, whichever subclass gets type-initialized last will "win" in setting the field.
Next, when you invoke BarFoo.GetName, that's really just a call to AbstractFoo.GetName - BarFoo won't get initialized, so you won't see the "pretty name" being set.
Fundamentally, I suggest you redesign your code. I recommend that you decorate each class with an attribute. That way you won't end up relying on the type initializer at all, and you don't need to declare a separate static member for each type. The only downside is that the value has to be a constant...
An alternative is to use a virtual property which is then overridden in subclasses - although that requires you to create an instance of each type, of course.

There is one copy of the static member. With your current setup, every subclass will overwrite that one copy, resulting in just one name being available. You need to make a static GetName function on every subclass and just return the name directly. I would recommend something along the lines of:
public abstract class AbstractFoo
{
}
public class BarFoo : AbstractFoo
{
public static string GetName()
{
return "Pretty Name For BarFoo";
}
}
Type fooType = typeof(AbstractFoo);
List<Assembly> assemblies = new List<Assembly>(AppDomain.CurrentDomain.GetAssemblies());
IEnumerable<Type> allTypes = assemblies.SelectMany<Assembly, Type>(s => s.GetTypes());
IEnumerable<Type> fooTypes = allTypes.Where(p => p.IsSubclassOf (fooType));
foreach (Type thisType in fooTypes)
{
MethodInfo method = thisType.GetMethod ("GetName", BindingFlags.Public | BindingFlags.Static);
string name = (string) method.Invoke (null, null);
// add to the list, anyhow names.Add (name);
}
Another way to do it would be to keep a Dictionary as a static member in AbstractFoo and have the subclass' static initializers add something to that dictionary.

Related

Iterating through fields with specific attribute

I'm pretty new to reflection in C#. I want to create a specific attribute that I can use with my fields, so I can go through them all and check that they are initialized properly, instead of writing these checks every time for every field. I think it would look something like this:
public abstract class BaseClass {
public void Awake() {
foreach(var s in GetAllFieldsWithAttribute("ShouldBeInitialized")) {
if (!s) {
Debug.LogWarning("Variable " + s.FieldName + " should be initialized!");
enabled = false;
}
}
}
}
public class ChildClass : BasicClass {
[ShouldBeInitialized]
public SomeClass someObject;
[ShouldBeInitialized]
public int? someInteger;
}
(You may notice that I intend to use it Unity3d, but there's nothing specific to Unity in this question — or at least, it seems so to me). Is this possible?
You can get this with a simple expression:
private IEnumerable<FieldInfo> GetAllFieldsWithAttribute(Type attributeType)
{
return this.GetType().GetFields().Where(
f => f.GetCustomAttributes(attributeType, false).Any());
}
Then change your call to:
foreach(var s in GetAllFieldsWithAttribute(typeof(ShouldBeInitializedAttribute)))
You can make this more useful throughout your app by making it an extension method on Type:
public static IEnumerable<FieldInfo> GetAllFieldsWithAttribute(this Type objectType, Type attributeType)
{
return objectType.GetFields().Where(
f => f.GetCustomAttributes(attributeType, false).Any());
}
You would call this as:
this.GetType().GetAllFieldsWithAttribute(typeof(ShouldBeInitializedAttribute))
Edit: To get private fields, change GetFields() to:
GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
And to get the type (inside your loop):
object o = s.GetValue(this);

Is it possible to access static methods of a static class without knowing the name of the static class

I'm just curious about this.. let's say i have N number of static classes that look exactly like the following besides the class name (let's pretend we have Bank1, Bank2, ... , BankN as class names)
static class Bank1{
private static List<string> customers = new List<string>();
static List<string> getCustomers(){
return customers;
}
Is it then possible to have a method that can access the getCustomers() method of each Bank class without knowing the name of the class? So for example
void printCustomers(string s)
{
*.getCustomers();
//for-loop to print contents of customers List
}
Where * stands for the class name which is passed in the string argument (doesn't have to be a string). Is there a way to do this without using something like
if(s.equals("Bank1")) {Bank1.getCustomers();}
else if (s.equals("Bank2")) {Bank2.getCustomers();}
etc?
You probably want to use reflection for this:
// s is a qualified type name, like "BankNamespace.Bank1"
var customers = (List<string>)
Type.GetType(s).InvokeMember("getCustomers",
System.Reflection.BindingFlags.Static |
System.Reflection.BindingFlags.InvokeMethod |
System.Reflection.BindingFlags.Public, // assume method is public
null, null, null);
If the class is known statically, you can use generics:
void printCustomers<T>()
{
T.getCustomers();
...
}
If the class is not known statically, then the natural solution is to use virtual methods (polymorphism), because that's the way to resolve methods at runtime.

Providing a Read Only List of Classes in C#

I have a set of custom data types that can be used to manipulate basic blocks of data. For example:
MyTypeA Foo = new MyTypeA();
Foo.ParseString(InputString);
if (Foo.Value > 4) return;
Some of these types define read-only properties that describe aspects of the types (for example a name, bit size, etc.).
In my custom framework I want to be able to provide these types to the user for use in their applications but I also want to give the user a list of the available types which they could easily bind to a combobox. My current approach:
public static class DataTypes
{
static ReadOnlyCollection<MyDataType> AvailableTypes;
static DataTypes()
{
List<MyDataType> Types = new List<MyDataType>();
Types.Add(new MyTypeA());
Types.Add(new MyTypeB());
AvailableTypes = new ReadOnlyCollection<MyDataType>(Types);
}
}
What concerns me about this is that the user might obtain a type from the AvailableTypes list (by selecting a combobox item for example) and then use that reference directly rather than creating a clone of the type and using their own reference.
How can I make the list of available types read only so that it doesn't allow any writing or changes to the type instances, forcing the user to create their own clone?
Alternatively is there a better way of providing a list of available types?
Thanks, Andy
Make your custom Type class immutable, same as System.Type and you dont have to worry. A end user can fetch all the data it wants but he can not modify the object in any way.
EDIT: Example of immutable class
Take the following class for instance:
public class ImmutablePerson
{
private readonly string name; //readonly ensures the field can only be set in the object's constructor(s).
private readonly int age;
public ImmutablePerson(string name, int age)
{
this.name = name;
this.age = age;
}
public int Age { get { return this.age; } } //no setter
public string Name { get { return this.name; } }
public ImmutablePerson GrowUp(int years)
{
return new ImmutablePerson(this.name, this.age + years); //does not modify object state, it returns a new object with the new state.
}
}
ImmutablePerson is an immutable class. Once created there is no way a consumer can modify it in any way. Notice that the GrowUp(int years) method does not modify the state of the object at all, it just returns a new instance of ImmutablePerson with the new values.
I hope this helps you understand immutable objects a little better and how they can help you in your particular case.
To get around the problems you've mentioned, you could create a wrapper around your instances, and have the wrapper provide the functionality you require.
For example:
public class TypeDescriptor
{
private MyDataType _dataType;
public TypeDescriptor(MyDataType dataType)
{
_dataType = dataType;
}
public override string ToString()
{
return _dataType.ToString();
}
}
You class would then look something like:
public static class DataTypes
{
public static ReadOnlyCollection<TypeDescriptor> AvailableTypes;
static DataTypes()
{
List<TypeDescriptor> Types = new List<TypeDescriptor>();
Types.Add(new TypeDescriptor(new MyTypeA()));
Types.Add(new TypeDescriptor(new MyTypeB()));
AvailableTypes = new ReadOnlyCollection<TypeDescriptor>(Types);
}
}
Binding to the list and relying on the ToString() will now result in your data types ToString being called.
Create a list of types rather than a list of instances. e.g.
List<Type> Types = new List<Type>();
Types.Add(typeof(MyTypeA));
Types.Add(typeof(MyTypeB()));
etc.
To answer the comment on binding to a drop down list:
MyDropDown.Datasource = Type.Select(t => t.Name);
MyDropDown.DataBind();
This will not use the custom property of your classes but it will give you the simple calss name without all the other guff e.g. MyTypeA
A collection cannot "inject" type modifiers into its members. The collection you have declared is readonly. If you want MyDataType to be readonly you must declare that way.
Somthing like :
EDIT extended class to have a parse method
public class MyDataType
{
private MyDataType()
{
...
}
internal static MyDataType Parse(string someString)
{
MyDataType newOne = new MyDataType();
newOne.Value = ... //int.Parse(someString); ?
}
public int Value { get; private set; }
}
If the collection stays generic there is no readonly constraint.
You would use it like this, following your example.
MyTypeA foo = MyTypeA.Parse(inputString);
if (foo.Value > 4) return;
You probably shouldn't store instances of your types in the list. Instead you can store types. These can be used to create instances:
public static class DataTypes
{
static ReadOnlyCollection<Type> AvailableTypes;
static DataTypes()
{
List<Type> Types = new List<Type>();
Types.Add(typeof(MyTypeA));
Types.Add(typeof(MyTypeB));
AvailableTypes = new ReadOnlyCollection<MyDataType>(Type);
}
}
You can use Activator.CreateInstance to create a concrete instance:
Object myType = Activator.CreateInstance(AvailableTypes[0]);
Unless your types share a common base type you cannot downcast the result and an Object isn't that useful.
Also the use of the term type in your code makes my example a bit confusing as I suggest you store the types of something called type.
You could consider creating and attribute that you then can apply to MyTypeA, MyTypeB etc. Then you can build the AvailableTypes using reflection and the list will always be up to date with your code. E.g. if you add MyTypeC and use the attribute it will automatically be added to the list.
You can also add a display string property to the attribute and use that for display in the combo box. If you want to do that you should store a small object combining the type and the display string in AvailableTypes.
Here is an example. Using generic words like type and data can be confusing so to pick a random name I just use foo. Obviously you should use a more descriptive name.
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
sealed class FooAttribute : Attribute {
public FooAttribute(String displayName) {
DisplayName = displayName;
}
public String DisplayName { get; private set; }
}
You can decorate you classes using this attribute:
[Foo("Type A")]
class MyTypeA { ... }
[Foo("Type B")]
class MyTypeB { ... }
For the combobox you want a list of factory objects with a nice ToString implementation (this class can be improved by adding some error handling which I have left out to save space):
class FooFactory {
readonly Type type;
public FooFactory(Type type) {
this.type = type;
DisplayName = ((FooAttribute) Attribute.GetCustomAttribute(
type,
typeof(FooAttribute))
).DisplayName;
}
public String DisplayName { get; private set; }
public Object CreateFoo() {
return Activator.CreateInstance(this.type);
}
public override String ToString() {
return DisplayName;
}
}
Returning Object from CreateFoo isn't very useful but that is a separate issue.
You can build this list at run-time:
var factories = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => Attribute.IsDefined(t, typeof(FooAttribute)))
.Select(t => new FooFactory(t));
I'm not exactly sure of what you want but should something like this be ok ?
public static class DataTypes
{
static Dictionary<string,Type> AvailableTypes
= new Dictionary<string,Type>()
{
{ "MyTypeA", MyTypeA },
{ "MyTypeB", MyTypeB },
...
};
}
That is actually return types instead of sample instances of theses types. Thus you would be sure that only new instances would be created by the user of your class.
Then in the calling code :
MyTypeA a = Activator.CreateInstance(DataTypes.AvailableTypes["MyTypeA"]);

Can one copy the contents of one object to another dynamically if they have the same interface?

For example, if I have two objects, one which is of type Monkey and the other of type Dog, and they both implement IAnimal, which is something like this:
interface IAnimal
{
int numberOfEyes {get; set;}
string name {get; set;}
}
I want to do something like this:
Monkey monkey = new Monkey() { numberOfEyes = 7, name = "Henry" };
Dog dog = new Dog();
MyFancyClass.DynamicCopy(monkey, dog, typeof(IAnimal));
Debug.Assert(dog.numberOfEyes == monkey.numberOfEyes);
I imagine one can create a class like MyFancyClass using reflection... any clever person have an idea?
Thanks,
Stephen
Just to throw it in the mix... you can also use AutoMapper to map/copy one object to another.... they don't even have to implement the same interface. To make it work automagically, just the names of the properties have to match and then you just do something like:
Mapper.Map<IAnimal, MyClass>(myInstance);
A reflection based solution follows. Note that the reflection work is done only once per Type and then cached, so the overhead should be minimal. Will work with .NET 3.5 and it is not restricted to interfaces.
Note that I use reflection to get all the properties on type T and filter to the properties that have both getters and setters. I then build an expression tree for each property that retrieves the value from the source and assigns that value to the target. The expression trees are compiled and cached in a static field. When the CopyProperties method is called, it invokes the copier for each property, copying all the properties defined in type T.
// Usage
Monkey monkey = new Monkey() { numberOfEyes = 7, name = "Henry" };
Dog dog = new Dog();
DynamicCopy.CopyProperties<IAnimal>(monkey, dog);
Debug.Assert(dog.numberOfEyes == monkey.numberOfEyes);
...
// The copier
public static class DynamicCopy
{
public static void CopyProperties<T>(T source, T target)
{
Helper<T>.CopyProperties(source, target);
}
private static class Helper<T>
{
private static readonly Action<T, T>[] _copyProps = Prepare();
private static Action<T, T>[] Prepare()
{
Type type = typeof(T);
ParameterExpression source = Expression.Parameter(type, "source");
ParameterExpression target = Expression.Parameter(type, "target");
var copyProps = from prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
where prop.CanRead && prop.CanWrite
let getExpr = Expression.Property(source, prop)
let setExpr = Expression.Call(target, prop.GetSetMethod(true), getExpr)
select Expression.Lambda<Action<T, T>>(setExpr, source, target).Compile();
return copyProps.ToArray();
}
public static void CopyProperties(T source, T target)
{
foreach (Action<T, T> copyProp in _copyProps)
copyProp(source, target);
}
}
}
Copy constructor is what I usually do:
class Monkey : IAnimal
{
public Monkey(IAnimal other)
{
//Copy properties here...
}
}
You have several options here:
You could go down the route of using reflection, but this will be much slower than other options, and you'll have to craft yoiur refleciton code. To make nice generic "clone" code using reflection is non-trivial, especially when you have to start catering for objects that contain lists/arrays/dictionaries of other object instances.
A copy constructor, as Dr Herbie mentioned, is one option.
Another would be to implement ICloneable on all your types (you could make you interface implement ICloneable to force all IAnimals to implement it). This may not be dynamic, like reflection (you'd have to hand craft it for each class), but assuming you just copy the property values accross, it'll be way faster than reflection.
Also worth thinking about is immutability. If you can make your concrete types immutable (using readonly on all fields so they can't be changed), then you probably don't need to worry about cloning at all. Everything can happily share the same instance safe in the knowledge that no other sharer can be modifying it in any way. This sort of immutability can be very powerful, although you need to be careful if your interface contains collections/arrays that can be modified.
Finally, if you have a lot of classes, you could look at code generation to generate C# "cloner" classes (whose job it is to generate a clone of a given type) and compile them into an assembly. You can use reflection here to create the "cloner class template", but since it generates code (that compiles with the rest of your project), you don't have the run-time hit of slow reflection.
So, there are lots of options for cloning - but using reflection, even though it can be naice and dynamic, is often not the best approach.
You could maKe IAnimal Implement ICloneable. Then do a memeberwise clone on the monkey or an other class that implements ICloneable. This is a shallow copy by the way.
public interface IAnmial : ICloneable
{
string Name{get; set;}
object Clone();
}
public class Monkey : IAnmial
{
public string Name{get; set;}
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Dog : IAnmial
{
public string Name{get; set;}
public object Clone()
{
return this.MemberwiseClone();
}
}
public class Test()
{
public void CloneAnimal()
{
Dog dog = new Dog()
{
Name = "MyAnimal",
};
IAnimal monkey = dog.Clone() as IAnimal;
}
}
As long as DynamicCopy takes in an IAnimal as a method parameter you can do that.
But it really helps to understand what you are trying to do.
Why not just implement a method in IAnimal?
(EDIT: As commenters have helpfully pointed out, IAnimal should be converted into an abstract base class Animal for this solution. This makes sense anyway, since the whole inference behind this question is that the child classes contain properties defined in the parent.)
// In Aminal class.
public void CopyAttributes(Animal source)
{
this.numberOfEyes = source.numberOfEyes;
this.name = source.name;
}
Doing something like this via reflection gets messy quick. Should you only copy properties? What about get/set methods? What about read-only properties? That is why it is probably best to define the behavior you actually want at each level. You can then override at lower levels if desired.
// In Monkey class.
public void CopyAttributes(Monkey source)
{
super.CopyAttributes(source);
this.numberOfTails = source.numberOfTails;
}
Try looking at struct methods

Treat subclass as its superclass when only a member differs by its type

I have a Variable class and and 3 subclasses: VariableBool, VariableLong and VariableDouble. Each subclass defines only a value member of the type of the suffix.
Now, I need to transfert objects based on these classes over WCF. I have multiple clients registering their variale to a server. Whenever a value changes on one client, it's updated in all other clients.
My question is: is there a way to do:
someVar.Value = anotherVar.Value;
regardless of the type, wihout having to check for type, e.g.:
VariableBool anotherVarBool = anotherVar as VariableBool;
if (anotherVarBool != null) {
(someVar as VariableBool).Value = anotherVar.Value;
}
// check other types...
What am I missing? Is there a patern of some kind? Could I use reflection?
Also, I don't think I can use Generics because of the WCF (I've tried but I could make it work).
Thanks
If you are using mex-generated WCF proxies, then I suspect reflection (or ComponentModel) is indeed the simplest option - something like:
public static void Copy<T>(T source, T destination,
string propertyName) {
PropertyInfo prop = typeof(T).GetProperty(propertyName);
prop.SetValue(destination, prop.GetValue(source, null), null);
}
Or if you want to use it even with the variable types as the base-class:
public static void Copy(object source, object destination,
string propertyName) {
PropertyInfo sourceProp = source.GetType().GetProperty(propertyName);
PropertyInfo destProp = destination.GetType().GetProperty(propertyName);
destProp.SetValue(destination, sourceProp.GetValue(source, null), null);
}
Why don't you to put the Value member in the base class Variable.
In that case,
public void UpdateValue( Variable variable )
{
if( variable != null )
// do something with variable.Value
}
However, if you really want to use inheritance, you need to tell the base class what are the sub types by using KnownType attribute and its method
[DataContract()]
[KnownType( "GetKnownType" )]
public class Variable
{
public object Value;
private static Type[] GetKnownType()
{
// properties
return new []{ typeof(VariableBool),
typeof(VariableLong),
typeof(VariableDouble),};
}
}
[DataContract()]
public class VariableBool : Variable
{
}
[DataContract()]
public class VariableLong : Variable
{
}
[DataContract()]
public class VariableDouble : Variable
{
}

Categories

Resources