I am using Reflection.Emit and I want to create a type that would be the equivalent of the following type defined in C#:
class A
{
public Tuple<A, int> GetValue(int x)
{
return new Tuple<A, int>(this, x);
}
}
The trick is that I need to use a generic type from BCL that uses my custom type as a generic argument.
I'm messing with the following snippet:
var asmName = new AssemblyName("Test");
var access = AssemblyBuilderAccess.Run;
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, access);
var module = asm.DefineDynamicModule("Test");
var aType = module.DefineType("A");
var tupleType = typeof(Tuple<,>).MakeGenericType(aType, typeof(int));
var attrs = MethodAttributes.Public;
var method = aType.DefineMethod("GetValue", attrs, tupleType, new [] { typeof(int) });
var gen = method.GetILGenerator();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
// here is the fail:
var ctor = tupleType.GetConstructor(new [] { typeof(int), aType } );
gen.Emit(OpCodes.Newobj, ctor);
The call to GetConstructor fails with the following exception:
NotSupportedException: Specified method is not supported.
So, basically, it won't let me get the constructor of a type that merely references my custom type, and neither can I finalize the type before emitting the body of its method.
Can it really be impossible to get out of this vicious circle?
For some reason, you need to use the static overload of GetConstructor() to do this. In your case, the code could look like this:
var ctor = TypeBuilder.GetConstructor(
tupleType, typeof(Tuple<,>).GetConstructors().Single());
Related
I want to invoke a method that expects a parameter like this:
Expression<Func<sometype, 'a>> expr
I need to construct this parameter at runtime, because I won't know what the anonymous type will look like before; it could have any amount of fields:
x => new { a=x.a, b=x.b, c=x.c, etc... }
I can create a type at runtime that has the same 'signature' (Is that the correct word for this?) as the desired anonymous type, but the question is: How do I construct this lambda expression at runtime from that? Especially Expression.New is bugging me, because I need to pass a constructorInfo to it that I have to get from an existing type (which can indeed be an anonymous type, but I can't create an anonymous type at runtime. Or is there a way to do that?).
Update (some context as requested in the comments)
The method I want to invoke is:
DependentNavigationPropertyConfiguration.HasForeignKey<TKey>(Expression<Func<TDependentEntityType, TKey>> foreignKeyExpression)
The reason I want to do this is to automatically make a navigation property to an entity that inherits from a certain base class include the key of that base class in the foreign key. Because an entity can have multiple key fields of any type, the type TKey is only known to me at runtime.
Use a separate method:
public static void Main()
{
var myExpression = Express(str => new {
String = str,
Length = str.Length
});
// We can compile/use it as well...
var compiledExpression = myExpression.Compile();
var anonymousOutput = compiledExpression("Input String");
Console.WriteLine(anonymousOutput.String); // Output: Input String
Console.WriteLine(anonymousOutput.Length); // Output: 12
Debug.WriteLine(myExpression); // Output: "str => new <>f__AnonymousType0`2(String = str, Length = str.Length)"
Console.ReadLine();
}
static Expression<Func<String, T>> Express<T>(Expression<Func<String, T>> expression)
{
return expression;
}
Note however, that the starting type (in my example String) must be known up front.
Update:
Since what it sounds like you're trying to do is dynamically create a type, I'll give you a simple example of how to do that.
public static void Main()
{
// Create an anonymous type with two fields
Type myAnonymousType = CreateNewType<String, Int32>();
dynamic myAnon = Activator.CreateInstance(myAnonymousType);
myAnon.FieldA = "A String";
myAnon.FieldB = 1234;
Console.WriteLine(myAnon.FieldA); // Output : "AString"
Console.WriteLine(myAnon.FieldB); // Output : 1234
Console.ReadLine();
}
public static Type CreateNewType<TFieldTypeA, TFieldTypeB>()
{
// Let's start by creating a new assembly
AssemblyName dynamicAssemblyName = new AssemblyName("MyAsm");
AssemblyBuilder dynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(dynamicAssemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder dynamicModule = dynamicAssembly.DefineDynamicModule("MyAsm");
// Now let's build a new type
TypeBuilder dynamicAnonymousType = dynamicModule.DefineType("MyAnon", TypeAttributes.Public);
// Let's add some fields to the type.
FieldInfo dynamicFieldA = dynamicAnonymousType.DefineField("FieldA", typeof(TFieldTypeA), FieldAttributes.Public);
FieldInfo dynamicFieldB = dynamicAnonymousType.DefineField("FieldB", typeof(TFieldTypeB), FieldAttributes.Public);
// Return the type to the caller
return dynamicAnonymousType.CreateType();
}
As you can see, this is a little more complicated. If you want to study the topic further though, definitely reference Reflection.Emit.
Anonymous types are a compiler feature. If you don't get the compiler to create them at compile-time, then you will have to use meta-programming - either TypeBuilder or maybe CSharpCodeProvider. You might be better off using tuples - at least they are easy to create (you can use Tuple.Create easily enough).
As for the expression; I would suggest typing it as Expression<Func<sometype, object>> - which will work for any formulation. The code inspecting the Expression can of course see what the actual type is.
you can do simply like this
context.Students.Join(context.Courses, a => a.Course_id, b => b.Course_id, (a, b) => new { Student= a, Course= b }).Where(x => x.Student_id == studentId)
.Select(y => new
{
StudentId = y.Student.StudentId,
RegistrationNumber = y.Student.RegNo,
Name = y.Student.Name,
Coursename = y.Course.Name
}).ToList();
I'm currently messing about with generics and I'm trying to write a function that I can call to load everything from a database table simply by specifying the table name.
I'm most of the way there; my generic methods all seem to work, but I'm not quite sure how to cast my results into something usable.
This is the guts of the method so far:
private static List<EntityCodeBase> GetCodeLoadResults(CodeTables table)
{
List<EntityCodeBase> results = new List<EntityCodeBase>();
Assembly assm = Assembly.Load(new System.Reflection.AssemblyName("RR"));
Type tableType = assm.GetTypes().Where(u => u.Name.ToLower() == table.ToString().ToLower()).FirstOrDefault();
MethodInfo mi = typeof(SpecificEntity).GetMethod("LoadAll");
mi = mi.MakeGenericMethod(tableType);
mi.Invoke(null, null); //how can I cast the resulting object into a List<EntityCodeBase> ?
return results;
}
Assuming SpecificEntity.LoadAll returns a list of some type derived from EntityCodeBase, you can't cast directly to a List<EntityCodeBase> but you can cast to IEnumerable<EntityCodeBase>. Then you can create a new list:
var ecbList = (IEnumerable<EntityCodeBase>)mi.Invoke(null, null);
return list.ToList();
It might be cleaner however, if you can get the table name from the entity type, either directly by name, using attributes, or using a map. Then you can make GetCodeLoadResults generic in the result type e.g.
private static List<T> GetCodeLoadResults() where T : EntityCodeBase
{
Assembly assm = Assembly.Load(new System.Reflection.AssemblyName("RR"));
Type tableType = //get table type from T
MethodInfo mi = typeof(SpecificEntity).GetMethod("LoadAll");
mi = mi.MakeGenericMethod(tableType);
return (List<T>)mi.Invoke(null, null);
}
If you're not using .Net 4, you can't cast a List<TDerived> to an IEnumerable<TBase>, so you'll have to cast to IEnumerable first:
return ((System.Collections.IEnumerable)mi.Invoke(null, null))
.Cast<EntityCodeBase>()
.ToList();
This is best explained using code. I have a generic class that has a method that returns an integer. Here is a simple version for the purposes of explaining...
public class Gen<T>
{
public int DoSomething(T instance)
{
// Real code does something more interesting!
return 1;
}
}
At runtime I use reflection to discover the type of something and then want to create an instance of my Gen class for that specific type. That is easy enough and done like this...
Type fieldType = // This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);
I now want to create an Expression that will take as a parameter an instance of the generic type and then calls the DoSomething method of that type. So I want the Expression to effectively perform this...
int answer = genericInstance.DoSomething(instance);
...except I do not have the 'instance' until some point later at runtime and the genericInstance is the generated type as can be seen above. My attempt at creating the Lambda for this is as follows...
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var x = Expression.Lambda<Func<genericType, fieldType, int>>
(Expression.Call(p1, mi, p2),
new[] { p1, p2 }).Compile();
...so that later on I can call it with something like this...
int answer = x(genericInstance, instance);
Of course, you cannot provide Func with instance parameters and so I have no idea how to parameterize the Lambda generation. Any ideas?
I think you would just use the Expression.Lambda that takes the delegate type as a type rather then as a generic, and create your Func on the fly like you are with Gen<>:
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var func = typeof (Func<,,>);
var genericFunc = func.MakeGenericType(genericType, fieldType, typeof(int));
var x = Expression.Lambda(genericFunc, Expression.Call(p1, mi, p2),
new[] { p1, p2 }).Compile();
This will return a Delegate rather than a strongly typed Func, but you can of course cast it if needed (and seemingly difficult if you don't know what you are casting to), or dynamically invoke it using DynamicInvoke on it.
int answer = (int) x.DynamicInvoke(genericInstance, instance);
EDIT:
A good idea that does indeed work. Unfortunately the reason I want to use a strongly typed compiled Lambda is performance. Using DynamicInvoke is prettty slow compared to a typed Lambda.
This seems to work without the need of a dynamic invoke.
var p1 = Expression.Parameter(genericType, "generic");
var p2 = Expression.Parameter(fieldType, "instance");
var func = typeof(Func<,,>);
var genericFunc = func.MakeGenericType(genericType, fieldType, typeof(int));
var x = Expression.Lambda(genericFunc, Expression.Call(p1, mi, p2), new[] { p1, p2 });
var invoke = Expression.Invoke(x, Expression.Constant(genericInstance), Expression.Constant(instance));
var answer = Expression.Lambda<Func<int>>(invoke).Compile()();
EDIT 2:
A greatly simplified version:
Type fieldType = ;// This is the type I have discovered
Type genericType = typeof(Gen<>).MakeGenericType(fieldType);
object genericInstance = Activator.CreateInstance(genericType);
MethodInfo mi = genericType.GetMethod("DoSomething",
BindingFlags.Instance | BindingFlags.Public);
var value = Expression.Constant(instance, fieldType);
var lambda = Expression.Lambda<Func<int>>(Expression.Call(Expression.Constant(genericInstance), mi, value));
var answer = lambda.Compile()();
This answer only applies if you are using .NET 4.0.
If you make genericInstance dynamic instead of object, you can then call the DoSomething method on it directly, and the dynamic language runtime will take care of everything for you.
class Type1 {
public int DoSomething() { return 1; }
}
class Type2 {
public int DoSomething() { return 2; }
}
static void TestDynamic() {
dynamic t1 = Activator.CreateInstance(typeof(Type1));
int answer1 = t1.DoSomething(); // returns 1
dynamic t2 = Activator.CreateInstance(typeof(Type2));
int answer2 = t2.DoSomething(); // returns 2
}
If you need to keep this class structure (Gen<T>), then I don't see an easy way around the fact that you don't know the type T at compile time. If you want to call the delegate, you either have to know its full type at compile time, or you need to pass in the parameters as objects.
Using dynamic gets you to hide the complexity of getting the MethodInfo, etc., and gives you excellent performance. The one drawback vs. DynamicInvoke that I see is that I believe you get the initial overhead of resolving the dynamic call once for every call site. The bindings are cached so that they run very fast from the second time onwards if you call it on objects with the same type.
It's better to to accept an object and use convert to a known type.
Here is an example, how to build access to a property by name on unknown depth:
var model = new { A = new { B = 10L } };
string prop = "A.B";
var parameter = Expression.Parameter(typeof(object));
Func<object, long> expr = (Func<object, long>) Expression.Lambda(prop.Split('.').Aggregate<string, Expression>(Expression.Convert(parameter, model.GetType()), Expression.Property), parameter).Compile();
expr(model).Dump();
It avoids extra costs of DynamicInvoke when type of delegate is unknown at compile time.
I'm using JB Evain's Mono.Cecil to perform some byte-code manipulation on compiled DLL's. Part of this project is to inject properties into TypeDefinitions, effectively turning compiled getters/setters into the C# Properties pattern using PropertyDefinitions. This part is working well.
However, I would like to add an indexer to the TypeDefinition but I cannot find any documentation or advice on how best to achieve this. The methods which will be used to process the index requests are already in place:
Object getObjectViaIndexer(String str);
void setObjectViaIndexer(String str, object obj);
All i need to do is add the metadata to convert these into indexers....
Any ideas / thoughts would be greatly apprecaited!
Indexers, metadata wise, are simple properties. Only the type is decorated with a special attribute to tell that the property is an indexer. Here's a sample implementation which adds a new Item property that is recognized as an indexer, and delegates to the existing methods.
TypeDefinition type = ...;
// public object get_Item (string str) { ... }
var get_item = new MethodDefinition ("get_Item", MethodAttributes.Public, module.TypeSystem.Object);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
type.Methods.Add (get_item);
var il = get_item.Body.GetILProcessor ();
il.Emit (...); // emit call to getObjectViaIndexer
// public void set_Item (string str, object obj) { ... }
var set_item = new MethodDefinition ("set_Item", MethodAttributes.Public, module.TypeSystem.Void);
set_item.Parameters.Add (new ParameterDefinition ("str", ParameterAttributes.None, module.TypeSystem.String));
set_item.Parameters.Add (new ParameterDefinition ("obj", ParameterAttributes.None, module.TypeSystem.Object));
type.Methods.Add (set_item);
il = set_item.Body.GetILProcessor ();
il.Emit (...); // emit call to setObjectViaIndexer
// public object this [string str] { ... }
var item = new PropertyDefinition ("Item", PropertyAttributes.None, module.TypeSystem.Object) {
HasThis = true,
GetMethod = get_item,
SetMethod = set_item,
};
type.Properties.Add (item);
// [DefaultMemberAttribute("Item")]
var default_member = new CustomAttribute (module.Import (typeof (System.Reflection.DefaultMemberAttribute).GetConstructor (new [] { typeof (string) })));
default_member.ConstructorArguments.Add (new CustomAttributeArgument(module.TypeSystem.String, "Item"));
type.CustomAttributes.Add (default_member);
Of course you could also just create a property which points to the existing methods, as long as you have the proper attribute.
I try create delegate type using an Expression class, but when I try create delegate from instance of MethodInfo I've got an ArgumentException. I using .NET 4.0
Here code:
var method = /*...*/;
List<Type> tArgs = new List<Type> { method.ReturnType };
var mparams = method.GetParameters();
mparams.ToList().ForEach(p => tArgs.Add(p.ParameterType));
var delDecltype = Expression.GetDelegateType(tArgs.ToArray());
return Delegate.CreateDelegate(delDecltype, method);
P.S. Sorry for my bad english;)
If you read the documentation for Expression.GetDelegateType(), you would see that the return type has to be the last argument.
That means this code should work:
var tArgs = new List<Type>();
foreach (var param in method.GetParameters())
tArgs.Add(param.ParameterType);
tArgs.Add(method.ReturnType);
var delDecltype = Expression.GetDelegateType(tArgs.ToArray());
return Delegate.CreateDelegate(delDecltype, method);
This code works for static methods only though. If you want create a delegate from instance method, you need to provide the instance you want to call the method on. To do that, change the last line to:
return Delegate.CreateDelegate(delDecltype, instance, method);