C# 如何使用泛型类型为要调用的方法传入函数?

C# 如何使用泛型类型为要调用的方法传入函数?,c#,generics,dependency-injection,delegates,C#,Generics,Dependency Injection,Delegates,编辑:我刚刚意识到我想要做的是遵循依赖注入模式,这是我从写了一篇关于这个主题的文章的人那里学到的。我希望有一个方法,在其中我进行一些设置,比如添加行,但传入一个将行写入上下文的对象。BulkInsert方法适用于大型“设置”,AddRange适用于小型设置 我有一个静态方法,其中我在DbContext中传递数据,并将行更新为多个实体。根据调用方法的方式,我想使用BulkInsert或AddRange public static void MySetup(MyContext, int addMet

编辑:我刚刚意识到我想要做的是遵循依赖注入模式,这是我从写了一篇关于这个主题的文章的人那里学到的。我希望有一个方法,在其中我进行一些设置,比如添加行,但传入一个将行写入上下文的对象。BulkInsert方法适用于大型“设置”,AddRange适用于小型设置

我有一个静态方法,其中我在DbContext中传递数据,并将行更新为多个实体。根据调用方法的方式,我想使用
BulkInsert
AddRange

public static void MySetup(MyContext, int addMethod)
{
    var list1 = new List<Foo>{......}
    if (addMethod = 1)
       context.BulkInsert(list1);
    else
       context.AddRange(list1);

    var list2 = new List<Bar>{......}
    if (addMethod = 1)
       context.BulkInsert(list2);
    else
       context.AddRange(list2);

}
publicstaticvoidmysetup(MyContext,int-addMethod)
{
var list1=新列表{……}
如果(addMethod=1)
插入上下文(列表1);
其他的
context.AddRange(列表1);
var list2=新列表{……}
如果(addMethod=1)
插入上下文(列表2);
其他的
AddRange(列表2);
}
我不想传入变量,而是想学习如何传入函数,所以它会像这样:

public static void MySetup(MyContext context, ??? myAdd)
{
    var list1 = new List<Foo>{......}
    myAdd(context, list1);

    var list2 = new List<Bar>{......}
    myAdd(context, list2);
}
publicstaticvoidmysetup(MyContext上下文,??myAdd)
{
var list1=新列表{……}
myAdd(上下文,列表1);
var list2=新列表{……}
myAdd(上下文,列表2);
}
我想我要找的是一名代表。请注意,我使用不同类型的列表类,因此在调用端设置的任何函数都需要接受一个通用列表(是吗?),因为我不想为每种可能的类型传入一个函数

预计到达时间:


BulkInsert和AddRange都通过EntityFramework添加行。他们每个人都有一张单子但是BulkInsert有一个可选的选项参数,因此可以像调用
上下文一样调用它。BulkInsert(myList,opts)

如果Foo和Bar共享一个公共接口,那么您可以使用

例如:

public interface IBaz
{
}

public class Foo : IBaz
{     
}

public class Bar : IBaz
{
}

public static void MySetup(DurianContext context, Action<DurianContext, List<IBaz>> addMethod)
{            
    List<IBaz> list1 = new List<IBaz>();
    addMethod(context, list1);

    List<IBaz> list2 = new List<IBaz>();
    addMethod(context, list2);
}
公共接口IBaz
{
}
公共类Foo:IBaz
{     
}
公共类酒吧:IBaz
{
}
公共静态void MySetup(DurianContext上下文,Action addMethod)
{            
List list1=新列表();
addMethod(上下文,列表1);
List list2=新列表();
addMethod(上下文,列表2);
}

如果Foo和Bar共享一个公共接口,那么您可以使用

例如:

public interface IBaz
{
}

public class Foo : IBaz
{     
}

public class Bar : IBaz
{
}

public static void MySetup(DurianContext context, Action<DurianContext, List<IBaz>> addMethod)
{            
    List<IBaz> list1 = new List<IBaz>();
    addMethod(context, list1);

    List<IBaz> list2 = new List<IBaz>();
    addMethod(context, list2);
}
公共接口IBaz
{
}
公共类Foo:IBaz
{     
}
公共类酒吧:IBaz
{
}
公共静态void MySetup(DurianContext上下文,Action addMethod)
{            
List list1=新列表();
addMethod(上下文,列表1);
List list2=新列表();
addMethod(上下文,列表2);
}
我认为您所需要的只是一个接受
IList
的代理,但是如果不知道
AddRange
AddBulk
方法的签名,就很难知道

public static void MySetup(MyContext context, Action<MyContext, IList> myAdd)
{
    var list1 = new List<Foo> { };
    myAdd(context, list1);

    var list2 = new List<Bar> { };
    myAdd(context, list2);
}
...

Action<MyContext, IList> insertRange = (context, list) =>
{
    context.AddRange(list);
};

Action<MyContext, IList> insertBulk = (context, list) =>
{
    context.BulkInsert(list);
};

MySetup(new MyContext(), insertRange);
// or...
MySetup(new MyContext(), insertBulk);
publicstaticvoidmysetup(MyContext上下文,actionmyadd)
{
var list1=新列表{};
myAdd(上下文,列表1);
var list2=新列表{};
myAdd(上下文,列表2);
}
...
Action insertRange=(上下文,列表)=>
{
context.AddRange(列表);
};
Action insertBulk=(上下文,列表)=>
{
插入上下文(列表);
};
MySetup(新的MyContext(),insertRange);
//或者。。。
MySetup(新的MyContext(),insertBulk);
我认为您所需要的只是一个接受
IList
的代理,但是如果不知道
AddRange
AddBulk
方法的签名,就很难知道

public static void MySetup(MyContext context, Action<MyContext, IList> myAdd)
{
    var list1 = new List<Foo> { };
    myAdd(context, list1);

    var list2 = new List<Bar> { };
    myAdd(context, list2);
}
...

Action<MyContext, IList> insertRange = (context, list) =>
{
    context.AddRange(list);
};

Action<MyContext, IList> insertBulk = (context, list) =>
{
    context.BulkInsert(list);
};

MySetup(new MyContext(), insertRange);
// or...
MySetup(new MyContext(), insertBulk);
publicstaticvoidmysetup(MyContext上下文,actionmyadd)
{
var list1=新列表{};
myAdd(上下文,列表1);
var list2=新列表{};
myAdd(上下文,列表2);
}
...
Action insertRange=(上下文,列表)=>
{
context.AddRange(列表);
};
Action insertBulk=(上下文,列表)=>
{
插入上下文(列表);
};
MySetup(新的MyContext(),insertRange);
//或者。。。
MySetup(新的MyContext(),insertBulk);

我考虑了很久,是否应该发布它(因为它确实回答了问题,但我不认为它解决了后面的问题),但就这样吧:

如果您事先知道所有可能使用的类型,最简单的方法是:

interface IAddStuff 
{
    void Add (MyContext context, IList<Foo> list);
    void Add (MyContext context, IList<Bar> list);
}

class Operations
{
    public static void MySetUp(MyContext context, IAddStuff adder)
    {
        var list1 = new List<Foo> ();
        adder.Add (context, list1);

        var list2 = new List<Bar> ();
        adder.Add (context, list2);
    }
}

class SampleImplementation : IAddStuff 
{
    public void Add(MyContext context, IList<Foo> list)
    {
        // ...
    }

    public void Add(MyContext context, IList<Bar> list)
    {
        // ...
    }
}
接口IAddStuff
{
void Add(MyContext上下文,IList列表);
void Add(MyContext上下文,IList列表);
}
班级作业
{
公共静态void MySetUp(MyContext上下文、IAddStuff加法器)
{
var list1=新列表();
adder.Add(上下文,列表1);
var list2=新列表();
adder.Add(上下文,列表2);
}
}
类示例实现:IAddStuff
{
public void Add(MyContext上下文,IList列表)
{
// ...
}
public void Add(MyContext上下文,IList列表)
{
// ...
}
}

现在,如果您不确切知道,仍然可以执行运行时调度(并由实现决定):

class MyContext{}
类Foo{}
类条{}
接口IADDSUFF
{
void Add(MyContext上下文,IList列表);
}
班级作业
{
公共静态void MySetUp(MyContext上下文、IAddStuff加法器)
{
var list1=新列表();
adder.Add(上下文,列表1);
var list2=新列表();
adder.Add(上下文,列表2);
}
}
类示例实现:IAddStuff
{
public void Add(MyContext上下文,IList列表)
{
if(typeof(T)=typeof(Foo))
AddFoo(context,list.Cast());
否则如果(类型(T)=类型(条形))
AddBar(context,list.Cast());
}
void AddFoo(MyContext上下文,IEnumerable列表)
{
// ...
}
void AddBar(MyContext上下文,IEnumerable列表)
{
// ...
}
}
现在,正如您所看到的,您只将问题(运行时检查您真正拥有哪种泛型类型)移动到了所述接口的实现中,但您可以让其他代码更干净一些

不知道你是否觉得这有用,但这是最近的