使用运行时创建的委托和对象

时间:2017-11-02 00:24:02

标签: c# linq reflection delegates

我一直在努力解决这个一般概念,所以是时候伸出援手了。我有一个LINQ查询,从SQL中选择一个字符串列表,然后调用Select并提供一个静态方法,它接收一个字符串并返回一个对象:

HEAD~5

我有一些不同的“配置文件”使用相同的查询但具有不同的类型。例如,除了MyClass之外,我还有一个MyOtherClass,它也有一个FromString方法,它接受一个字符串参数,但返回一个自己的实例。从查询中获取列表之后,我想在其上调用Distinct,提供在运行时再次确定的比较器委托。

我总是遇到这种问题的类型是构建时的类型。我知道我可以像这样创建比较器:

MyDataContext context = new MyDataContext();
var list = (
    from t in context.GetTable<FooTable>()
    where t.FooType = userProvidedString
    select t.SomeColumn).ToList()
        .Select(colValue => MyClass.FromString(colVal))
        .ToList();
int unique = list.Distinct(new MyClassComparer()).Count();

但是当我在ctor上调用Invoke时,我仍然会得到一个必须被投射的对象。我确信这可以做到,而我只是缺少一些关键概念。请给我一个顿悟! 提前谢谢......

1 个答案:

答案 0 :(得分:0)

&#34;建设性意见&#34;让我朝着正确的方向前进,这是我想出的解决方案。

public void Foo()
{
    string dataType = "MyClass"; // Pretend this string was specified by the user
    Type t = Type.GetType(dataType);
    Type u = Type.GetType(dataType + "Comparer"); // Implements IEqualityComparer<MyClass>
    MethodInfo method = this.GetType().GetMethod("GetUniqueItemCount", BindingFlags.Instance | BindingFlags.NonPublic);
    MethodInfo generic = method.MakeGenericMethod(t, u);

    int count = (int)generic.Invoke(this, new object[] { "some data blah blah" });
}

private void GetUniqueItemCount<T, U>(string data) where T : class
                                                   where U : IEqualityComparer<T>, new()
{
    MyDataContext context = new MyDataContext();
    var list = (
        from v in context.GetTable<SomeTable>()
        select v.SomeColumn).ToList()
            .Select(cellValue => Activator.CreateInstance(typeof(T), new object[] { cellValue }) as T)
            .ToList();
    return list.Distinct(new U()).Count();
}

令人遗憾的是,我不得不使用Activator.CreateInstance因为&#34;新的T()&#34;只能与无参数构造函数一起使用。这不是很好,因为它会在查询结果集中调用每个项目。

我在创建T和U并调用方法时所做的所有反思都是我在帖子中提到的(并希望避免)。这个解决方案应该在这里完全说明我的意图,所以如果你知道一个更清洁的方法,请加入。

再次感谢您的帮助!