gpt4 book ai didi

c# - 如何发出委托(delegate)或 lambda 表达式

转载 作者:行者123 更新时间:2023-11-30 14:20:41 25 4
gpt4 key购买 nike

我想发出一个返回 Func<> 的方法。在此方法中,我必须创建一个完全符合返回类型的委托(delegate)或 lambda 表达式。

总的来说应该是这样的:

// I have a resolve method that will be called inside my missing method
// This is it's signature:
object Resolve( params object[] args);

// This is how I use it:
var barFactory = ( Func<IBar> )MissingMethod( typeof( IBar ) );
var bar = barFactory.Invoke();

// or - with one string argument:
var fooFactory = ( Func<string, IFoo> )MissingMethod( typeof( IFoo ), typeof( string ) );
var foo = fooFactory.Invoke( "argument for foo" );

在 MissingMethod() 内部它应该是这样的:

object MissingMethod( Type returnType, params Type[] argTypes )
{
// Create the type of Func<> based on the passed returnType and the argTypes
var funcType = typeof(Func<,...,>).MakeGenericType( ... )

// Here I have to use the Resolve() method and cast the lambda to the correct type
return (cast to funcType)( (arg1, arg2) => Resolve( arg1, arg2 ) );
}

我认为获得 MissingMethod() 的唯一方法是使用 reflection.emit。

您是否知道有关发射 lambda 或委托(delegate)的好资源或教程?

您是否看到了此问题的另一种可能解决方案?

编辑:
这是我想要实现的场景:

static void Main()
{
var container = new Container();
container.Register<Foo>();
container.Register<ConsumerClass>();

var consumerClass = Container.Resolve<ConsumerClass>();
}

class Foo()
{
public Foo( string argument ) {}
}

class ConsumerClass
{
public ConsumerClass( [Inject] Func<string, Foo> factory )
{
var foo1 = factory.Invoke( "first foo" );
var foo2 = factory.Invoke( "another foo" );
// ...
}
}

我正在尝试实现 Container 和 Resolve() 方法。我知道注册了一个“Foo”类型。我知道它的构造函数需要调用一个字符串。

当我必须解析类型“ConsumerClass”时,我看到它想要注入(inject)一个 Func。这并不是我的容器所能提供的,因为通常它会像这样为 Foo 提供单个实例:

Container.Resolve<Foo>( "argument" );

但是尽管如此,容器也应该能够提供 Func。它具有所有需要的信息。

但现在我被困在创建这个绑定(bind) Func<,> 中。记住它也可以是 Func<,,,>。所以我正在寻找一种可以即时创建我的委托(delegate)的解决方案。它们必须可转换为确切的绑定(bind)类型。

编辑:
我不确定如何更好地描述它...我正在尝试做类似 this 的事情.但我不想通过目标。而不是

delegate void object LateBoundMethod( object target, object[] arguments );

我的委托(delegate)应该是这样的

delegate void object LateBoundMethod( object[] arguments );

并且目标作为实例字段提供。通过采用并“改进”Marc 的解决方案,我得到:

private Delegate CreateDelegate( Type returnType, Type[] parameterTypes )
{
m_Type = returnType;

var i = 0;
var param = Array.ConvertAll( parameterTypes, arg => Expression.Parameter( arg, "arg" + i++ ) );
var asObj = Array.ConvertAll( param, p => Expression.Convert( p, typeof( object ) ) );
var argsArray = Expression.NewArrayInit( typeof( object ), asObj );

var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );
var body = Expression.Convert( callEx, returnType );

var ret = Expression.Lambda( body, param ).Compile();
return ret;
}

private readonly Container m_Container;
private Type m_Type;

public object Resolve( params object[] args )
{
return m_Container.Resolve( m_Type, args );
}

但这还不完整。 Resolve() 方法不再是静态的(因为它需要两个实例字段)并且不能被调用。所以这里的问题是

var callEx = Expression.Call( null, typeof( FuncFactory ).GetMethod( "Resolve" ), argsArray );

我认为我需要引用“this”而不是将 null 作为第一个参数传递。我该怎么做?

最佳答案

第一个问题是Func<...>不存在 - 您需要编码为 Func<> , Func<,> , Func<,,> , Func<,,,>分别。

现在;我理解代码,但我不确定您要解决的场景是什么……您能澄清一下吗?可能有更好的选择...

如果它像听起来那么复杂,一个自定义的 Expression可能是最合适的选项(比 Reflection.Emit 简单得多)。


这有效,例如...

static Delegate MissingFunc(Type result, params Type[] args)
{
int i = 0;
var param = Array.ConvertAll(args,
arg => Expression.Parameter(arg, "arg" + i++));
var asObj = Array.ConvertAll(param,
p => Expression.Convert(p, typeof(object)));
var argsArray = Expression.NewArrayInit(typeof(object), asObj);
var body = Expression.Convert(Expression.Call(
null, typeof(Program).GetMethod("Resolve"),
argsArray), result);
return Expression.Lambda(body, param).Compile();
}
static void Main()
{
var func2 = MissingFunc(typeof(string), typeof(int), typeof(float));
}
public static object Resolve( params object[] args) {
throw new NotImplementedException();
}

关于c# - 如何发出委托(delegate)或 lambda 表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/939956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com