我正在使用Code Emit进行动态代码生成。 我想使用外部工厂方法设置一个字段。 这是我的(简化)代码:
定义:
Func<object> fact = () => new B();
var mi = fact.GetMethodInfo();
var t = typeof(B);
发射代码:
ILGenerator ilg;
var tb = _mb.DefineType("myProxy", TypeAttributes.Public | TypeAttributes.Class, typeof(object));
var fieldBuilder = tb.DefineField("proxy", t, FieldAttributes.Private);
var ctorBuilder = tb.DefineConstructor(...);
ilg = ctorBuilder.GetILGenerator();
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
ilg.Emit(OpCodes.Ldarg_0);
ilg.Emit(OpCodes.Callvirt, mi);
ilg.Emit(OpCodes.Castclass, t);
ilg.Emit(OpCodes.Stfld, fieldBuilder);
ilg.Emit(OpCodes.Ret);
创建一个实例:
Activator.CreateInstance(tb.CreateType());
抛出TargetInvocationException
{“找不到方法:\”?\“。”}
以下是我期待的结果:
public class A
{
private B _proxy;
public A(Func<object> factory)
{
_proxy = (B)factory();
}
}
但是工厂方法是固定的,不作为参数提供......
public class A
{
private B _proxy;
public A()
{
_proxy = (B) //[GENERATE ME] () => new B();
}
}
任何建议?
答案 0 :(得分:0)
你必须通过&#34; Invoke&#34;来调用委托。方法,但您需要将工厂代理提供给您的代理。您可以向代理构造函数添加参数。
public class B
{
}
static internal class Metadata<T> //Avoid lock & string metadata description
{
static public readonly Type Type = typeof(T);
static public FieldInfo Field<X>(Expression<Func<T, X>> expression)
{
return (expression.Body as MemberExpression).Member as FieldInfo;
}
static public PropertyInfo Property<X>(Expression<Func<T, X>> expression)
{
return (expression.Body as MemberExpression).Member as PropertyInfo;
}
static public MethodInfo Method(Expression<Action<T>> expression)
{
return (expression.Body as MethodCallExpression).Method;
}
static public MethodInfo Method<X>(Expression<Func<T, X>> expression)
{
return (expression.Body as MethodCallExpression).Method;
}
}
class Program
{
static void Main(string[] args)
{
var _Factory = new Func<object>(() => new B());
TypeBuilder _TypeBuilder = null;// = ...;
var _Parameters = new Type[] { Metadata<Func<object>>.Type };
var _Constructor = _TypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, _Parameters);
var _Body = _Constructor.GetILGenerator();
//...
_Body.Emit(OpCodes.Ldarg_1);
_Body.Emit(OpCodes.Call, Metadata<Func<object>>.Method(_Func => _Func.Invoke()));
//...
var _Type = _TypeBuilder.CreateType();
var _Parameter = Expression.Parameter(Metadata<Func<object>>.Type);
var _New = Expression.Lambda<Func<Func<object>, object>>(Expression.New(_Type.GetConstructor(_Parameters), _Parameter), _Parameter).Compile();
var _Instance = _New(_Factory);
}
}