I have a generic interface that requires a read and key method. I want to use reflection to get an instance of each implementation.
Once I have a the implementation, I want to get it's key and store the key and the instance in a dictionary.
Eventually, I would have a method where I pass in a key and byte[], it would look the key up in the dictionary and use the instance that it retrieves to read the byte[] and return an object.
I hope this is understandable, if not I can answer questions in the comments.
This example only has int and string, but I'll have many more types in my real implementation.
The Goal
To have a dictionary with 2 entries stored as such:
43, IRead<int> new Reader()
61, IRead<string> new Reader()
public interface IRead<T>
{
T Read(bool[] binary);
int Key( T type );
}
public class Reader : IRead<int>, IRead<string>
{
int IRead<int>.Read( byte[] binary )
{
// does stuff
returns 4;
}
public int Key( int type ) { return 43; }
string IRead<string>.Read( byte[] binary )
{
// does stuff
returns "example";
}
public int Key( string type ) { return 61; }
static StreamProcessor( )
{
// Here I want to get the definitions
}
}
Please, when you ask a question, post code that compiles. It makes life easier for everyone (perhaps your answer is because the pseudocode you wrote is wrong?)
In any case, this will get all types which implement IRead<>:
var types = GetType().Assembly.GetTypes()
.Select(t => new
{
Type = t,
MatchingInterfaces = t.GetInterfaces()
.Where(i => i.GetGenericTypeDefinition() == typeof(IRead<>))
})
.Where(t => t.MatchingInterfaces.Any())
Your pre-requisite of returning the key doesn't make that much sense. You can't find all instances of IRead<>. And you need an instance to give you a key.
For example, what would your dictionary look like if you had this code:
var readerOne = new Reader();
var readerTwo = new Reader();
Which instance goes into the dictionary?
The closest you can get is to:
Pass the method a list of objects and return the key of those instances
Create a dummy instance of each type to get the key
Make the key method static, and not part of the interface.
I suggest breaking this up because there are a few different things you're trying to do - some are clear, some aren't.
First you want to get types that implement IReader:
public IEnumerable<Type> GetTypes<TAssignableFrom>()
{
return this.GetType().Assembly.GetTypes()
.Where(type => type.IsAssignableFrom(typeof (TAssignableFrom)));
}
What do you want to do with those types? If you want to create an instance of each type then either they need to have parameterless constructors or otherwise identical constructors, or you'd need to be using some dependency injection container.
Let's say that they're going to have parameterless constructors. We can update the above to
public IEnumerable<Type> GetTypes<TAssignableFrom>()
{
return this.GetType().Assembly.GetTypes()
.Where(type => type.IsAssignableFrom(typeof (TAssignableFrom))
&& type.GetConstructor(Type.EmptyTypes) != null
);
}
Now you've got a bunch of types that you can instantiate.
From there it gets pretty fuzzy. What will you do with those types? It's not much use to put them into a dictionary because they are all different types.
Related
Task:
Serialize a list of objects into a byte[] using protobuf.
Without reflection all is good
.proto
message MyObject{
int32 id = 1;
int32 value = 2;
}
message MyObjects {
repeated MyObject objects = 1;
}
.cs
public static byte[] ToByteArray(List<MyObject> obj) {
var objects = new MyObjects {
Objects = {obj}
};
return objects.ToByteArray();
}
Since I need to serialize many different types in this way, I want to write a universal method using reflection.
Problem:
Protobuf itself generates entities and properties for them, but it does not create a setter for RepeatedField, which means that I can not set the value using GetProperty("Objects")?.SetValue(objects, obj). System.ArgumentException: Set Method not found for 'Objects'
.cs (protobuf generated)
public pbc::RepeatedField<global::Test.MyObject> Objects {
get { return objects_; }
}
.cs
public static byte[] ToByteArray<T, E>(List<T> obj) where T : IMessage where E : IMessage {
var objects = Activator.CreateInstance<E>();
objects.GetType().GetProperty("Objects")?.SetValue(objects, obj);
return objects.ToByteArray();
}
Question:
How to use reflection to set values for a property during object creation, just as I do it without reflection?
How to write this "new MyObjects {Objects = {obj}}; (where obj: IEnumerable)" using reflection
Various conclusions:
I noticed that filling properties that do not have a setter is only possible for collections and only when creating an object.
Most likely I need an alternative way to instantiate the class. Activator.CreateInstance() is not fulfilling my task.
When we do this:
var x = new Thing
{
SomeProperty = "x",
SomeOtherProperty = 1
}
we aren't setting the values during object creation. This is the equivalent of:
var x = new Thing();
x.SomeProperty = "x";
x.SomeOtherProperty = 1;
In both cases the properties are set after the object is instantiated by setting their properties. An easy way to verify this is to try using the syntax from the first example to set a property that doesn't have a setter. It won't compile. You'll see this error:
Property or indexer 'Thing.SomeProperty' cannot be assigned to -- it is read-only.
In other words, the object, as defined, does not provide a way to set the Objects property.
The question is whether you really need to set the property. Quite likely you only need to add items to the collection.
Doing this with reflection is still really ugly. I don't recommend this at all. This is a crude version. It can fail at runtime for all sorts of reasons.
public static byte[] ToByteArray<T, E>(List<T> itemsToAdd) where T : IMessage where E : IMessage
{
// create an instance of the object
var created = Activator.CreateInstance<E>();
// Find the "Objects" property. It could be null. It could be the wrong type.
var objectsProperty = typeof(E).GetProperty("Objects");
// Get the value of the objects property. Hopefully it's the type you expect it to be.
var collection = objectsProperty.GetValue(created);
// Get the Add method. This might also be null if the method doesn't exist.
var addMethod = collection.GetType().GetMethod("Add");
// invoke the Add method for each item in the collection
foreach(var itemToAdd in itemsToAdd)
{
addMethod.Invoke(collection, new object[] { itemToAdd });
}
return created.ToByteArray();
}
Unless we're forced to, we really don't want to do that. I don't know what your IMessage type look like.
Does it have the Objects property?
In that case you could just do this:
public static byte[] ToByteArray<T, E>(List<T> itemsToAdd)
where T : IMessage
where E : IMessage, new()
{
var created = new E();
foreach (var itemToAdd in itemsToAdd)
{
created.Objects.Add(itemToAdd);
}
// or skip the foreach and just do
// created.Objects.AddRange(itemToAdd);
return created.ToByteArray();
}
I'm guessing about whether your interface has that property. But if at all possible, you're better off doing this with generic constraints than with reflection. This way your code is checked for most possible errors when it compiles, as opposed to running it and having it blow up because this or that property or method doesn't exist, is wrong, etc.
The new() constraint simply means that E must be a type with a default constructor, which means that in order for it to compile, E must be a type you can create without passing anything to the constructor. (Without that constraint, new E() won't compile.)
Without that constraint even Activator.CreateInstance might fail because the the type might not have a default constructor.
Scott's answer solves the problem, but I used a shortened solution in the end
private static byte[] ToByteArray<T, E>(IEnumerable<T> obj) where T : IMessage where E : IMessage, new() {
var objects = new E();
(objects.GetType().GetProperty("Objects")?.GetValue(objects) as RepeatedField<T>)?.AddRange(obj);
return objects.ToByteArray();
}
I'm on a quest to write a TypedBinaryReader that would be able to read any type that BinaryReader normally supports, and a type that implements a specific interface. I have come really close, but I'm not quite there yet.
For the value types, I mapped the types to functors that call the appropriate functions.
For the reference types, as long as they inherit the interface I specified and can be constructed, the function below works.
However, I want to create an universal generic method call, ReadUniversal<T>() that would work for both value types and the above specified reference types.
This is attempt number one, it works, but It's not generic enought, I still have to cases.
public class TypedBinaryReader : BinaryReader {
private readonly Dictionary<Type, object> functorBindings;
public TypedBinaryReader(Stream input) : this(input, Encoding.UTF8, false) { }
public TypedBinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) { }
public TypedBinaryReader(Stream input, Encoding encoding, bool leaveOpen) : base(input, encoding, leaveOpen) {
functorBindings = new Dictionary<Type, object>() {
{typeof(byte), new Func<byte>(ReadByte)},
{typeof(int), new Func<int>(ReadInt32)},
{typeof(short), new Func<short>(ReadInt16)},
{typeof(long), new Func<long>(ReadInt64)},
{typeof(sbyte), new Func<sbyte>(ReadSByte)},
{typeof(uint), new Func<uint>(ReadUInt32)},
{typeof(ushort), new Func<ushort>(ReadUInt16)},
{typeof(ulong), new Func<ulong>(ReadUInt64)},
{typeof(bool), new Func<bool>(ReadBoolean)},
{typeof(float), new Func<float>(ReadSingle)}
};
}
public T ReadValueType<T>() {
return ((Func<T>)functorBindings[typeof(T)])();
}
public T ReadReferenceType<T>() where T : MyReadableInterface, new() {
T item = new T();
item.Read(this);
return item;
}
public List<T> ReadMultipleValuesList<T, R>() {
dynamic size = ReadValueType<R>();
List<T> list = new List<T>(size);
for (dynamic i = 0; i < size; ++i) {
list.Add(ReadValueType<T>());
}
return list;
}
public List<T> ReadMultipleObjecsList<T, R>() where T : MyReadableInterface {
dynamic size = ReadValueType<R>();
List<T> list = new List<T>(size);
for (dynamic i = 0; i < size; ++i) {
list.Add(ReadReferenceType<T>());
}
return list;
}
}
An idea that I came up with, that I don't really like, is to write generic class that boxes in the value types, like this one:
public class Value<T> : MyReadableInterface {
private T value;
public Value(T value) {
this.value = value;
}
internal Value(TypedBinaryReader reader) {
Read(reader);
}
public T Get() {
return value;
}
public void Set(T value) {
if (!this.value.Equals(value)) {
this.value = value;
}
}
public override string ToString() {
return value.ToString();
}
public void Read(TypedBinaryReader reader) {
value = reader.ReadValueType<T>();
}
}
This way, I can use ReadReferencTypes<T>() even on value types, as long as I pass the type parameter as Value<int> instead of just int.
But this is still ugly since I again have to remember what I'm reading, just instead of having to remember function signature, I have to remember to box in the value types.
Ideal solution would be when I could add a following method to TypedBinaryReader class:
public T ReadUniversal<T>() {
if ((T).IsSubclassOf(typeof(MyReadableInterface)) {
return ReadReferenceType<T>();
} else if (functorBindings.ContainsKey(typeof(T)) {
return ReadValueType<T>();
} else {
throw new SomeException();
}
}
However, due to different constraints on the generic argument T, this won't work. Any ideas on how to make it work?
Ultimate goal is to read any type that BinaryReader normally can or any type that implements the interface, using only a single method.
If you need a method to handle reference types and a method to handle value types, that's a perfectly valid reason to have two methods.
What may help is to view this from the perspective of code that will call the methods in this class. From their perspective, do they benefit if they can call just one method regardless of the type instead of having to call one method for value types and another for value types? Probably not.
What happens (and I've done this lots and lots of times) is that we get caught up in how we want a certain class to look or behave for reasons that aren't related to the actual software that we're trying to write. In my experience this happens a lot when we're trying to write generic classes. Generic classes help us when we see unnecessarily code duplication in cases where the types we're working with don't matter (like if we had one class for a list of ints, another for a list of doubles, etc.)
Then when we get around to actually using the classes we've created we may find that our needs are not quite what we thought, and the time we spent polishing that generic class goes to waste.
If the types we're working with do require entirely different code then forcing the handling of multiple unrelated types into a single generic method is going to make your code more complicated. (Whenever we feel forced to use dynamic it's a good sign that something may have become overcomplicated.)
My suggestion is just to write the code that you need and not worry if you need to call different methods. See if it actually creates a problem. It probably won't. Don't try to solve the problem until it appears.
I have written a function which will take a generic IEnumerable and map these objects (if possible) to objects I want to use for an algorithm. I don't have a lot of experience with generic objects or IEnumerables, so I wanted to ask for some advice.
I have written this code:
public static IEnumerable<OtherObject> MyObjectToOtherObject<T>(IEnumerable<T> objects)
{
if (objects.GetType() == typeof(MyObject))
{
var data = (IEnumerable<MyObject>)objects;
return data.Select(x => new OtherObject() { // Map the attributes });
}
else
return null;
}
This doesn't work in my code, since it returns null even though the input list is of the type MyObject. I just can't figure out how to cast my IEnumerable<T> to IEnumerable<MyObject>. Is there something I'm doing wrong?
Thanks in advance!
I'm sorry for all the confusion. I have asked this the wrong way. Alex has helped me enough, thank you!
this is wrong.
objects.GetType() == typeof(MyObject)
Correct:
objects.GetType() == typeof(IEnumerable<T>)
If you need to compare type of nested items:
objects.GetType().GetGenericArguments()[0] == typeof(MyObject)
typeof(T) == typeof(MyObject)
If you are checking if the type can be casted to another type:
objects.GetType().GetGenericArguments()[0].IsAssignableFrom(typeof(MyObject))
or just as
typeof(T).IsAssignableFrom(typeof(MyObject))
Doesn't look like you need a generic method, if you always know the source and destination types, you can do this:
public static IEnumerable<DestObject> ObjectToObject1(IEnumerable<SourceObject> objects)
{
return data.Select(x => new DestObject() { // Map the attributes });
}
I think what you're trying to do is build a generic mapping method which can map any give T to your concrete class Object1. You need to provide a mapping function which does the mapping.
Say you have this (overly contrived) example:
public class SourceObject
{
public string AString{get;set;}
}
public class DestObject
{
public string TheProperty{get;set;}
}
And you start with an IEnumerable<SourceObject> your method would need to take the list, and a Func<SourceObject,DestObject> to do the mapping
var input = new List<SourceObject>(){
new SourceObject{AString="Str1"},
new SourceObject{AString="Str2"}
};
var result = MyObjectToOtherObject(input, x => new DestObject{TheProperty = x.AString});
This is accomplished like so:
public static IEnumerable<DestObject> MyObjectToOtherObject<T>(IEnumerable<T> objects, Func<T,DestObject> mapping)
{
return data.Select(mapping);
}
As you can see, the separate method is more-or-less useless at this point. It's exactly what Select does.
objects will never be of type MyObject, therefore
(objects.GetType() == typeof(MyObject))
will always return false because object is some generic collection (IEnumerable<T>).
you could try using
typeof(T) == typeof(MyObject)
Is it possible to check if the list contains an object of given (but dynamic) type, derrived from same basic abstract class?
The main problem is not about the list, but about comparing types itself.
In single variables and static variables, it's easy:
if(someVariable is int)
Checking the list with static type is also easy, like:
SomeList.OfType<int>().Any()
or
(from _Object in SomeList.OfType<int> where _Object is int select _Object).Count() == 0
but I cant't handle it if the type I want to check is dynamic, f.e. passed as method parameter:
abstract class BasicClass;
class DerivativeOne : BasicClass { }
class DerivativeTwo : BasicClass { }
// in main:
List<BasicClass> _List = new List<BasicClass>();
DerivativeOne a = new DerivativeOne();
DerivativeTwo b = new DerivativeTwo();
DerivativeOne c = new DerivativeOne();
if(!CheckIfTypeExistsInList(a, _List)
{
_List.Add(a);
}
if(!CheckIfTypeExistsInList(b, _List)
{
_List.Add(b);
}
if(!CheckIfTypeExistsInList(c, _List)
{
_List.Add(c); // this is what I don't want to happen,
// because I already have one object of type DerivativeOne in my list.
}
// the function:
bool CheckIfTypeExistsInList(BasicClass pObject, List<BasicClass> pList)
{
/// few attempts:
pList.OfType<(pObject.GetType()>().Any(); // attempt one, error
return (from _Object in SomeList.OfType<(pObject.GetType())> where _Object is int select _Object).Count() == 0; // attempt two, error
}
PS. I am aware that the code doesn't look neat, but I tried to show just the problem itself, skipping extra logic and stuff.
PS2. I am aware that the solution to the problem would be just to put some attribute to BasicClass and make each derivative to have unique value of the attribute, but still - I'm not looking for another route to solve the problem, I'm just interested if it's possible to do it "this" way.
When the type is known only at runtime, you cannot use it in a generic without using reflection. However, your task is simpler than that - you can use type equality to achieve the results that you want:
Type targetType = pObject.GetType();
if (SomeList.Any(o => targetType.Equals(o.GetType()))) {
...
}
I have a factory method that returns the correct sub class depending on three enum values.
One way to do is, would be to use switches in switches in switches. Obviously, I don't like that option very much.
I thought that another option would be to use attributes in C#. Every sub class would have an attribute with that 3 enum values and in the factory I would only have to get the class that has the same enum values corresponding to the enum values i have in the factory.
However, I am quite new to attributes and I did not find any suitable solution in the web. If anyone, could just give me some hints or some lines of code, I really would appreciate that!
First of all, declare your attribute and add it to your classes.
enum MyEnum
{
Undefined,
Set,
Reset
}
class MyEnumAttribute : Attribute
{
public MyEnumAttribute(MyEnum value)
{
Value = value;
}
public MyEnum Value { get; private set; }
}
[MyEnum(MyEnum.Reset)]
class ResetClass
{
}
[MyEnum(MyEnum.Set)]
class SetClass
{
}
[MyEnum(MyEnum.Undefined)]
class UndefinedClass
{
}
Then, you can use this code to create a dictionary with your enums and types, and dynamically create a type.
//Populate a dictionary with Reflection
var dictionary = Assembly.GetExecutingAssembly().GetTypes().
Select(t => new {t, Attribute = t.GetCustomAttribute(typeof (MyEnumAttribute))}).
Where(e => e.Attribute != null).
ToDictionary(e => (e.Attribute as MyEnumAttribute).Value, e => e.t);
//Assume that you dynamically want an instance of ResetClass
var wanted = MyEnum.Reset;
var instance = Activator.CreateInstance(dictionary[wanted]);
//The biggest downside is that instance will be of type object.
//My solution in this case was making each of those classes implement
//an interface or derive from a base class, so that their signatures
//would remain the same, but their behaviors would differ.
As you can probably notice, calling Activator.CreateInstance is not performant. Therefore, if you want to improve the performance a little bit, you can change the dictionary to Dictionary<MyEnum,Func<object>> and instead of adding types as values you would add functions wrapping the constructor of each of your classes and returning them as objects.
EDIT: I'm adding a ConstructorFactory class, adapted from this page.
static class ConstructorFactory
{
static ObjectActivator<T> GetActivator<T>(ConstructorInfo ctor)
{
var paramsInfo = ctor.GetParameters();
var param = Expression.Parameter(typeof(object[]), "args");
var argsExp = new Expression[paramsInfo.Length];
for (var i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
var paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
var newExp = Expression.New(ctor, argsExp);
var lambda = Expression.Lambda(typeof(ObjectActivator<T>), newExp, param);
var compiled = (ObjectActivator<T>)lambda.Compile();
return compiled;
}
public static Func<T> Create<T>(Type destType)
{
var ctor = destType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).First();
Func<ConstructorInfo, object> activatorMethod = GetActivator<Type>;
var method = typeof(ConstructorFactory).GetMethod(activatorMethod.Method.Name, BindingFlags.Static | BindingFlags.NonPublic);
var generic = method.MakeGenericMethod(destType);
dynamic activator = generic.Invoke(null, new object[] { ctor });
return () => activator();
}
delegate T ObjectActivator<out T>(params object[] args);
}
You can use it as an alternative to Activator.CreateInstance, it provides greater performance if the result is cached.
var dictionary = Assembly.GetExecutingAssembly().GetTypes().
Select(t => new { t, Attribute = t.GetCustomAttribute(typeof(MyEnumAttribute)) }).
Where(e => e.Attribute != null).
ToDictionary(e => (e.Attribute as MyEnumAttribute).Value,
e => ConstructorFactory.Create<object>(e.t));
var wanted = MyEnum.Reset;
var instance = dictionary[wanted]();
Have a look at this article: Creating Custom Attributes. You can then use reflection (for instance GetCustomAttributes) to get the attributes and their values.
Hope this helps
[AttributeUsage(AttributeTargets.Class)]
public class SampleClass : Attribute {
public SampleClass() : base() { }
public SampleClass(YourEnum attributeValue) : this() { MyAttributeProperty = attributeValue; }
public YourEnum MyAttributeProperty { get; set; }
}
public enum YourEnum { Value1, Value2, Value3 }
[SampleClass(YourEnum.Value1)]
public class ExampleValue1Class { }
public class LoadOnlyClassesWithEnumValue1 {
public LoadOnlyClassesWithEnumValue1() {
Type[] allTypes = Assembly.GetExecutingAssembly().GetExportedTypes();
foreach (var type in allTypes) {
if (type.GetCustomAttributes(typeof(SampleClass), false).Length > 0) {
SampleClass theAttribute = type.GetCustomAttributes(typeof(SampleClass), false).Single() as SampleClass;
// this type is using SampleClass - I use .Single() cause I don't expect multiple SampleClass attributes, change ths if you want
// specify true instead of false to get base class attributes as well - i.e. ExampleValue1Class inherits from something else which has a SampleClass attribute
switch (theAttribute.MyAttributeProperty) {
case YourEnum.Value1:
// Do whatever
break;
case YourEnum.Value2:
// you want
break;
case YourEnum.Value3:
default:
// in your switch here
// You'll find the ExampleValue1Class object should hit the Value1 switch
break;
}
}
}
}
}
This way you can specify your enum as a parameter to the attribute. In essence, this is a very simple and lightweight DI container.
I'd suggest for anything more complex, to use something like StructureMap or NInject.
Another solution would be to use Dependency Injection (DI) container. For instance using Unity DI you can:
// Register a named type mapping
myContainer.RegisterType<IMyObject, MyRealObject1>(MyEnum.Value1.ToString());
myContainer.RegisterType<IMyObject, MyRealObject2>(MyEnum.Value2.ToString());
myContainer.RegisterType<IMyObject, MyRealObject3>(MyEnum.Value3.ToString());
// Following code will return a new instance of MyRealObject1
var mySubclass = myContainer.Resolve<IMyObject>(myEnum.Value1.ToString());
Examples on using Unity:
Implementing the Microsoft Unity (Dependency Injection) Design Pattern
Of course you can use any DI container (Castle Windsor, StructureMap, Ninject. Here is a list some of the available .NET DI containers List of .NET Dependency Injection Containers (IOC)
It is possible to use attributes to hold the information, but ultimately the decision process will still have to be made and will likely not be much different; just with the added complexity of the attributes. The nature of the decision remains the same regardless of where you get the information to make the decision, from the existing three enumerations or from attributes.
It may prove more fruitful to look for a way to combine the three enumerations.
Enums can be any integral type, so the easiest way to eliminate nested (and redundant) switches is to combine the enumerations together. This is easiest if the enumeration is a collection of flag values. That is, each value of the enumeration has the value of a single bit in a binary string (1 for the first bit, 2 for the second bit, 4 for the third, 8, 16 and so on).
Provided the values of each of the enumerations can be joined together it reduces the selection process to a single switch statement. This may be best done by concatenating, multiplying or adding the enumeration values -- but how they are joined together depends on the enumerations, and without knowing more details it is hard to provide more definite direction.