Generics and Type inference - c#

I have an abstract generic class BLL<T> where T : BusinessObject. I need to open an assembly that contains a set of concrete BLL classes, and return the tuples (businessObjectType, concreteBLLType) inside a Dictionary. There is the part of the method I could do until now, but I'm having problems to discover T.
protected override Dictionary<Type, Type> DefineBLLs()
{
string bllsAssembly = ConfigurationManager.AppSettings["BLLsAssembly"];
Type[] types = LoadAssembly(bllsAssembly);
Dictionary<Type, Type> bllsTypes = new Dictionary<Type, Type>();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(BLL<>)))
/* how to know T in the situation below? */
bllsTypes.Add(??businessObjectType (T)??, type);
}
return bllsTypes;
}

So the concrete classes will be closed rather than generic? Here's a short program which demonstrates what I think you're after...
using System;
using System.Reflection;
public abstract class Base<T>
{
}
public class Concrete : Base<string>
{
}
class Test
{
static void Main()
{
Type type = typeof(Concrete);
Type baseType = type.BaseType;
Type typeOfT = baseType.GetGenericArguments()[0]; // Only one arg
Console.WriteLine(typeOfT.Name); // Prints String
}
}
Note that here I'm assuming that we only need to go up one level to get to the appropriate base type, and that the concrete class will be closed. You'd want to put more checks into your real code, of course, but I suspect it was the call to GetGenericArguments that you were missing.

Jon, that is exactly what I was looking for. I use the basics of reflection and generics, so when it is needed a more profound knowledge of the API to confront both, I miss things like this one, thanks for answering.
Your assumptions are right, the concrete classes are closed, and T is defined on the base class (BLL).
The code became into this:
protected override Dictionary<Type, Type> DefineBLLs()
{
string bllsAssembly = ConfigurationManager.AppSettings["BLLsAssembly"];
Type[] types = LoadAssembly(bllsAssembly);
Dictionary<Type, Type> bllsTypes = new Dictionary<Type, Type>();
foreach (Type bllType in types)
{
if (bllType.IsSubclassOf(typeof(BLL<>)))
{
Type baseType = bllType.BaseType;
Type businessObjectType = baseType.GetGenericArguments()[0];
bllsTypes.Add(businessObjectType, bllType);
}
}
return bllsTypes;
}

Related

is it necessary to use MakeGenericType method?

I saw code like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Program {
public static void Main() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using TKey=String, TValue=Int32
Type closedType = openType.MakeGenericType(typeof(string), typeof(int));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
Console.WriteLine(o.GetType());
}
}
But why we need to use the MakeGenericType method, why not just do:
...
Type concreteType= typeof(MyDictionary<string, int>);
Object o = Activator.CreateInstance(concreteType);
Console.WriteLine(o.GetType());
the results are the same.
It looks like MakeGenericType method add extra unnecessity, so does MakeGenericType provide useful features that I overlook?
MakeGenericType is for when you don't know the type at compile time. Therefore you are correct - you wouldn't really use the code you saw, as the types were known at compile time, so you may as well write new MyDictionary<string, int>().
However, the code could rewritten like this:
internal sealed class MyDictionary<TKey, TValue> { }
public static class Factory {
public static MyDictionary<TKey, TValue> Create<TKey, TValue>() {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using type constraints
Type closedType = openType.MakeGenericType(typeof(TKey), typeof(TValue));
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (MyDictionary<TKey, TValue>)o;
}
}
These two would effectively create the same object:
var dictionary0 = new MyDictionary<string, int>();
var dictionary1 = Factory.Create<string, int>();
Console.WriteLine(dictionary0.GetType() == dictionary1.GetType());
// true
Even here it's not that useful because the return type requires generic constraints. Where I use it is for situations that require an interface or abstract return type, but you need to create a generic implementation, for example:
internal sealed class MyDictionary<TKey, TValue> : ISomeFeature { }
public static class Factory {
public static ISomeFeature Create(Type key, Type value) {
// Get a reference to the generic type's type object
Type openType = typeof(MyDictionary<,>);
// Close the generic type by using arguments
Type closedType = openType.MakeGenericType(key, value);
// Construct an instance of the closed type
Object o = Activator.CreateInstance(closedType);
return (ISomeFeature)o;
}
}
Now suddenly it becomes a whole lot more useful. Because it relies on Type objects instead of generic constraints, you can pass it types dynamically - i.e. at run time.
Short answer: NO! it is not necessary to use makeGenericType, but sometimes it's a necessity
Generics are best used when you know the types at compile time. In fact there is a good argument that if you don't know the types at compile time, you probably shouldnt be using generics!
That said, there are often times when you need to use a generic implementation (perhaps a 3rd party library) and you only know the types at runtime... that is where Reflection, and specifically MakeGenericType comes in.
You code was no doubt an example of how to do this, because actually that code is only doing
var dict = new MyDictionary<string,int>();
Console.WriteLine(dict.GetType());
Assuming the types were known at compile time.

c# - can convert from C# type to System.Type but not vice-versa

I can create a generic class that takes, as its template parameter, a C# type, and then within the generic class use the System.Type information corresponding to that C# type:
public class Generic<T>
{
public bool IsArray()
{
return typeof(T).IsArray();
}
public T Create()
{
return blah();
}
}
Generic<int> gi = new Generic<int>();
Debug.WriteLine("int isarray=" + gi.IsArray());
Generic<DateTime> gdt;
But now let's say what I have, is a System.Type. I can't use this to instantiate my generic class:
FieldInfo field = foo();
Generic<field.FieldType> g; // Not valid!
Is there some clever C# thing I can do, to convert a System.Type back to the original C# type? Or some other way, to create a generic that can (1) give me information about the System.Type, and (2) create objects of the associate C# type?
By the way, this is a very contrived example to explain the problem I'm trying to solve, don't worry too much about whether Generic makes sense or not!
The only thing you can do is use reflection. This because while the int of Generic<int> is known at compile-time, the field.FieldType is known only at runtime.
Reflection example:
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
// Object of type Generic<field.FieldType>
object gen = Activator.CreateInstance(type);
But even here, from a Type (field.FieldType) you obtain another Type (type)
There are normally three ways of using this:
Full reflection: you use the object of type Generic<type> only through reflection. You create it through Activator.CreateInstance and from there you begin using Type.GetMethod() and Invoke()
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
// Object of type Generic<field.FieldType>
object gen = Activator.CreateInstance(type);
MethodInfo isArray = type.GetMethod("IsArray");
bool result = (bool)isArray.Invoke(gen, null);
Interfaces/base classes: you have a non-generic base class or interface that is common between all the Generic<T>. You use your object only though that interface/base class.
public class Generic<T> : IComparable where T : new()
{
public bool IsArray()
{
return typeof(T).IsArray;
}
public T Create()
{
return new T();
}
public int CompareTo(object obj)
{
return 0;
}
}
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
IComparable cmp = (IComparable)Activator.CreateInstance(type);
int res = cmp.CompareTo(cmp);
A generic method where you put all the handling of the Generic<T>. That is the only method that is used through reflection.
public static void WorkWithT<T>() where T : new()
{
Generic<T> g = new Generic<T>();
T obj = g.Create();
Console.WriteLine(g.IsArray());
}
var method = typeof(Program).GetMethod("WorkWithT").MakeGenericMethod(field.FieldType);
// Single reflection use. Inside WorkWithT no reflection is used.
method.Invoke(null, null);

How to instantiate Generic class object?

I am trying to convert the following c# code into java
abstract class BaseProcessor<T> where T : new()
{
public T Process(HtmlDocument html)
{
T data = new T();
Type type = data.GetType();
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty;
PropertyInfo[] properties = type.GetProperties(flags);
foreach (PropertyInfo property in properties)
{
string value = "test";
type.InvokeMember(property.Name, flags, Type.DefaultBinder, data, new object[] { value });
}
}
}
So i have done upto
public class BaseProcessor<T>
{
public T Process(String m_doc)
{
T data = (T) new BaseProcessor<T>(); // this is not working
Document doc = Jsoup.parse(m_doc);
return data;
}
}
When i instantiate the data object its not acquiring the properties of the Generic class at runtime
let say for example when i hit the code its not getting properties of DecodeModel class
IDocProcessor<DecodeModel> p = new DecodeThisProcessor();
return p.Process(doc);
public interface IDocProcessor<T>
{
T Process(String webresponse);
}
public class DecodeThisProcessor extends BaseProcessor<DecodeModel> implements IDocProcessor<DecodeModel>
{
public void setup();
}
So please help me what will be the right syntax to instantiate generic object data
You cannot instantiate generics. The reason is that the type is not available at run-time, but actually replaced with Object by the compiler. So
T data = new T(); // Not valid in Java for a generics T!
would in fact be:
Object data = new Object(); // Obviously not the desired result
Read the Java Generics Tutorial wrt. to "type erasure" for details.
You will need to employ the factory pattern.
T data = factory.make();
where
public interface Factory<T> {
T make();
}
needs to be implemented and passed to the constructor. To make this work, you need a factory that knows how to instantiate the desired class!
A (rather obvious) variant is to put the factory method into your - abstract - class.
public abstract class BaseProcessor<T>
{
protected abstract T makeProcessor();
public T Process(String m_doc)
{
T data = makeProcessor(); // this is now working!
and when extending BaseProcessor implement it for the actual final type.
Tough luck; in Java the whole of Generics is strictly a compile-time artifact and the instantiation of the type parameters doesn't exist in the runtime. The usual workaround is to pass an instance of Class as a marker, which will allow you to reflectively create an object of that type. This is fraught with many pitfalls, but is the best you can get in Java.
You can do this:
public class BaseProcessor<T>
{
private Class<T> clazz;
public BaseProcessor(Class<T> clazz)
{
this.clazz = clazz;
}
public T Process(String m_doc)
{
T data = clazz.newInstance()
Document doc = Jsoup.parse(m_doc);
return data;
}
}
Hint: Make sure that T has a no-arg constructor.

c# pluggable factory / static initialization

I am looking for a c# equivelent of my code for a pluggable factory. The advantage of the linked method is that static initialization result in a push operation, where each plugin adds itself to the factory.
C++ code for a pluggable factory: (http://codepad.org/7pgzaaAK)
// base class for plugins
class Foo{
public:
virtual std::string getName()const=0;
virtual void exercise()const=0;
};
// plugin factory
class FooFactory{
public:
static Foo* GetA(std::string s);
typedef std::map<std::string,Foo*(*)(void)> mapType;
static mapType& getA();
};
FooFactory::mapType& FooFactory::getA(){static mapType getA;return getA;}
Foo* FooFactory::GetA(std::string s)
{return getA().find(s)!=getA().end()?getA()[s]():0;} // to simplify access
// helper function to add the fun
template<typename T>
Foo* getNew(){ return new T; }
// use the CRTP to automatically register the object with the factory.
template <typename T> struct Reg { Reg() { /*cout << "registering a " << T().getName( <<endl;*/
FooFactory::getA().insert(std::pair<std::string, Foo*(*)()>(T().getName(), &getNew<T>));} };
template <typename T>
class Foo_reg:public Foo{
public:
Foo_reg(){®}; // using a reff to the static is enough to force initialization of the static earlier
static Reg<T> reg;
};
template <typename T> Reg<T> Foo_reg<T>::reg;
/////////////////
class FooBar:public Foo_reg<FooBar>{ // automatic registration with the factory
public:
FooBar(){a=10;}
virtual std::string getName()const{return "Foo Bar";}
virtual void exercise()const {cout <<a;}
private:
int a;
};
// exercise the factory and objects.
int main(){
Foo* foo=FooFactory::GetA("Foo Bar");
foo->exercise();
}
In C# i can see 2 ways of doing this, both of them pull operations
Have an explicit pre-built list of all plugins, which has to be maintained seperatly from the plugins themselves.
Use code reflection to iterate through all types, checking if they are castable to Foo and initialize their statics, on any dll load and program start.
Is it possible to do this without having to resort to these methods?
I wouldnt worry about reflection to much. Even PEX has no trouble using it. Simply put, by reflection, you're just checking the metadata of an assembly and see if it defined any classes that implement a certain interface or are marked with a certain attribute, this is very fast! Anyways, the CLR will never run code that is not being called explicitly so no, you have to resort to some kind of pulling mechanism (even if you make it look like a push mechanism)
realizing that the only real requiremnt here was that at the end of the day we have a lookup between a type identifier (string/Type) and a function which allows us to get an instance of that type i ended up resolving this with the following pattern:
private static readonly Dictionary<string, KeyValuePair<TConstructor, Node>> Types =
new Dictionary<string, KeyValuePair<TConstructor, Node>>();
private static readonly Dictionary<Type, string> classNameMap = new Dictionary<Type, string>();
private class constructableNode<T> where T : Node, new()
{
public constructableNode()
{
var t = new T();
Types[t.Type()] = new KeyValuePair<TConstructor, Node>(thisTConstructor, t);
classNameMap[typeof (T)] = t.Type();
}
private static T thisTConstructor()
{
var t = new T();
return t;
}
}
public static Node GetA(string s)
{
if (Types.ContainsKey(s) == false)
{
UpdateAvailableTypes();
}
if (Types.ContainsKey(s) == false)
{
throw new BadNodeType(s);
}
// look up the correct constructor, and call it.
return Types[s].Key();
}
public static void UpdateAvailableTypes()
{
Assembly targetAssembly = Assembly.GetExecutingAssembly(); // or whichever - could iterate dlls in the plugins folder or something
UpdateAvailableTypes(targetAssembly);
classNameMap[typeof (Node)] = "BaseNode"; // HARD CODED INTO the node type itself also
}
private static void UpdateAvailableTypes(Assembly targetAssembly)
{
IEnumerable<Type> subtypes = targetAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof (Node)));
Type nodeConstructor = typeof (constructableNode<>);
foreach (Type currentType in subtypes)
{
// this line throwing an error means that the Node type does not have an empty constructor.
Activator.CreateInstance(nodeConstructor.MakeGenericType(currentType));
}
}
This is a simple method, but the cost of the dynamic Invoke each call is a bit steep compared to other options, and when i first used this pattern for the section below, it was 80% of the critical code path runtime.
HOWEVEVER: Due to performance constraints a different pattern of construction was needed for part of my code which was rebuilt quickly (potentially millions of objects, wanted sub-second response time). (see discussion at http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx for various methods of reflection based construction)
for these i needed the following construction paradigm, whereby the intermediate lookup through the function call to the generic class was washed out
static buildCostItems()
{
//from http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx
AssemblyBuilder asmBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("inmemory"),
AssemblyBuilderAccess.Run);
ModuleBuilder modBldr = asmBldr.DefineDynamicModule("helper");
TypeBuilder typeBldr = modBldr.DefineType("ClassFactory");
Type tci = typeof (CostsItem);
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where(tci.IsAssignableFrom);
//// Note -- assumption of currently executing assembly -- this isn't a requirement, but didn't need the dynamic callback capabilities of the Node constructor here.
List<Type> enumerable = types as List<Type> ?? types.ToList();
foreach (Type type in enumerable)
{
MethodBuilder methBldr = typeBldr.DefineMethod(type.Name,
MethodAttributes.Public | MethodAttributes.Static, type,
new[] {typeof (CostsItem)});
ILGenerator ilgen = methBldr.GetILGenerator();
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Newobj, type.GetConstructor(new[] {typeof (CostsItem)}));
ilgen.Emit(OpCodes.Ret);
}
Type baked = typeBldr.CreateType();
foreach (Type type in enumerable)
ctors.Add(type,
(CtorCloneDelegate)
Delegate.CreateDelegate(typeof (CtorCloneDelegate), baked.GetMethod(type.Name)));
}

Pass An Instantiated System.Type as a Type Parameter for a Generic Class

The title is kind of obscure. What I want to know is if this is possible:
string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);
MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();
Obviously, MyGenericClass is described as:
public class MyGenericClass<T>
Right now, the compiler complains that 'The type or namespace 'myType' could not be found." There has got to be a way to do this.
You can't do this without reflection. However, you can do it with reflection. Here's a complete example:
using System;
using System.Reflection;
public class Generic<T>
{
public Generic()
{
Console.WriteLine("T={0}", typeof(T));
}
}
class Test
{
static void Main()
{
string typeName = "System.String";
Type typeArgument = Type.GetType(typeName);
Type genericClass = typeof(Generic<>);
// MakeGenericType is badly named
Type constructedClass = genericClass.MakeGenericType(typeArgument);
object created = Activator.CreateInstance(constructedClass);
}
}
Note: if your generic class accepts multiple types, you must include the commas when you omit the type names, for example:
Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);
Unfortunately no there is not. Generic arguments must be resolvable at Compile time as either 1) a valid type or 2) another generic parameter. There is no way to create generic instances based on runtime values without the big hammer of using reflection.
Some additional how to run with scissors code. Suppose you have a class similar to
public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}
Suppose at runtime you have a FooContent
If you were able to bind at compile time you would want
var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)
However you cannot do this at runtime. To do this at runtime you would do along the lines of:
var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);
To dynamically invoke Markdown(IEnumerable<FooContent> contents)
new Encoder().Markdown( (dynamic) dynamicList)
Note the usage of dynamic in the method call. At runtime dynamicList will be List<FooContent> (additionally also being IEnumerable<FooContent>) since even usage of dynamic is still rooted to a strongly typed language the run time binder will select the appropriate Markdown method. If there is no exact type matches, it will look for an object parameter method and if neither match a runtime binder exception will be raised alerting that no method matches.
The obvious draw back to this approach is a huge loss of type safety at compile time. Nevertheless code along these lines will let you operate in a very dynamic sense that at runtime is still fully typed as you expect it to be.
My requirements were slightly different, but will hopefully help someone. I needed to read type from a config and instantiate the generic type dynamically.
namespace GenericTest
{
public class Item
{
}
}
namespace GenericTest
{
public class GenericClass<T>
{
}
}
Finally, here is how you call it. Define the type with a backtick.
var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);
If you know what types will be passed you can do this without reflection. A switch statement would work. Obviously, this would only work in a limited number of cases, but it'll be much faster than reflection.
public class Type1 { }
public class Type2 { }
public class Generic<T> { }
public class Program
{
public static void Main()
{
var typeName = nameof(Type1);
switch (typeName)
{
case nameof(Type1):
var type1 = new Generic<Type1>();
// do something
break;
case nameof(Type2):
var type2 = new Generic<Type2>();
// do something
break;
}
}
}
In this snippet I want to show how to create and use a dynamically created list. For example, I'm adding to the dynamic list here.
void AddValue<T>(object targetList, T valueToAdd)
{
var addMethod = targetList.GetType().GetMethod("Add");
addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}
var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);
AddValue(list, 5);
Similarly you can invoke any other method on the list.

Categories