我有很多子类,从IDbTypeHandler<T>继承而来, 我想知道如何将"SetValue"转换为lambda表达式,然后我可以呼叫Action<IDbDataParameter, object>.

接口

    public interface IDbTypeHandler
    {
    }
    public interface IDbTypeHandler<T> : IDbTypeHandler
    {
        void SetValue(IDbDataParameter parameter, T value);
    }

班级

    internal class UniqueidentifierUlIdHandler : IDbTypeHandler<UlId>
    {
        public void SetValue(IDbDataParameter parameter, UlId value)
        {
            parameter.Value = value.ToByteArray();
        }
    }
    internal class Char1Handler : IDbTypeHandler<bool>
    {
        public void SetValue(IDbDataParameter parameter, bool value)
        {
            parameter.Value = value;
        }
    }

-update

下面的代码是我想要创建lambda表达式的地方

if (!TryGetValue("Key", out IDbTypeHandler dbTypeHandler))
{
   return false;
}

var t = dbTypeHandler.GetType();
var itf = t.GetInterfaces().SingleOrDefault(i => i.IsGenericType);
var xx = itf.GenericTypeArguments[0];

var p0 = Expression.Parameter(t);
var p1 = Expression.Parameter(typeof(IDbDataParameter));
var p2 = Expression.Parameter(xx);
var method = t.GetMethod("SetValue");
Type delegateType = typeof(Action<,,>).MakeGenericType(t, typeof(IDbDataParameter), xx);
var lambda = Expression.Lambda(delegateType, Expression.Call(p0, method, p1, p2), new[] { p0, p1, p2 });

现在,我得到了一辆Lambda.如果我使用.Compile(),那么它将返回Delegate类型.但是,我想要Action<IDbDataParameter,object>

我知道我需要在var lambda = Expression.Lambda之前进行打字转换,但我现在不知道该怎么做.

推荐答案

我用两种方法重新创建了一个小示例来实现lambda(参见第test1test2类)

internal class Program
{
    static void Main(string[] args)
    {
        var one = new One();
        var two = new Two();

        var obj_int = new ClassX();
        var obj_str = new ClassX();

        var ActOne = new test1<int, One>();
        var ActTwo = new test1<string, Two>();

        ActOne.myLambda1(obj_int, 10, one);
        ActTwo.myLambda1(obj_str, "Youpi", two);

        Console.WriteLine($"one = {obj_int.Value} two = {string.Join(",",(char[])obj_str.Value)}");

        new test2<int, One>().myLambda2(obj_int, 20);
        new test2<string, Two>().myLambda2(obj_str, "Super");

        Console.WriteLine($"one = {obj_int.Value} two = {string.Join(",", (char[])obj_str.Value)}");
    }

}
//lambda with U instantiated
public class test1<T,U> where U : ITest<T>
{
    public Action<ClassX, T, U> myLambda1 = (arg1, arg2, arg3) =>
    {
        arg3.SetValue(arg1, arg2);
    };
}
//lambda with U not instantiated
public class test2<T, U> where U : ITest<T> , new()
{ 
    public Action<ClassX, T> myLambda2 = (arg1, arg2) =>
    {
        new U().SetValue(arg1, arg2);
    };
}

public class ClassX
{
    public object Value;
}

public interface ITest<T>
{
    void SetValue(ClassX parameter, T value);
}
public class One : ITest<int>
{
    public void SetValue(ClassX parameter, int value)
    {
        parameter.Value = value + 10;
    }
}

public class Two : ITest<string>
{
    public void SetValue(ClassX parameter, string value)
    {
        parameter.Value = value.ToCharArray();
    }
}

结果:

one = 20 two = Y,o,u,p,i
one = 30 two = S,u,p,e,r

Csharp相关问答推荐

为什么EF Core 6会针对null验证Count(*)?

Entity Framework Core 8 dbcontext—无法以多对多关系添加某些行'

"virtual"修饰符对接口成员有什么影响?

REST API端点中异步后台代码执行的类型

Nuget包Serilog.Sinks.AwsCloudwatch引发TypeLoadExceptions,因为父类型是密封的

有没有办法在WPF文本框中添加复制事件的处理程序?

将轮询与超时同步

StackExchange.Redis.RedisServerException:调用ITransaction.ExecuteAsync()时出现错误未知命令取消监视

共享暂存/生产环境中Azure事件中心的建议配置

TeamsBot SendActivityActivityTypes与ActivityTypes同步.键入不再起作用

具有类型识别的泛型方法

在C#.NET项目中启动时,如何等待提升的PowerShell进程退出?

为什么我的伺服电机不动,下面的代码?

如何对特定异常使用Polly重试机制?

如何解决System.StackOverflowException:抛出System.StackOverflowException类型的异常.&# 39;生成随机代码时发生异常?

从HTML元素获取 colored颜色

在C#中通过Matheval使用自定义公式

反序列化我以前使用System.Text.Json序列化的文件时出现异常

客户端/服务器RPC如何处理全局变量?

Avalonia MVVM数据模板