Son*_*Ali 0 c# generics generic-method
给出以下接口:
interface IEntity
{
int Id{get;}
}
interface IPerson : IEntity
{
string Name{get;}
int Age{get;}
}
interface ITeacher : IPerson
{
string StaffId{get;}
}
interface IStudent : IPerson
{
string StudentId{get;}
string Courses{get;}
}
interface IRepository
{
T Get<T>(int id) where T : IEntity
}
Run Code Online (Sandbox Code Playgroud)
我的命名空间中有以下类
public class EntityBase() : IEntity
{
int Id{get;set;}
}
public class Teacher : EntityBase, ITeacher{}
public class Sudent : EntityBase, IStudent{}
Run Code Online (Sandbox Code Playgroud)
目前我正在实现这个IRepository,如下所示:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
if(typeof(T) == typeof(Teacher))
return Context.Get<ITeacher>(id);
if(typeof(T) == typeof(Sudent))
return Context.Get<ISudent>(id);
throw new Exception("Unknown Interface " + typeof(T).Name);
}
}
Run Code Online (Sandbox Code Playgroud)
是否有更好的实施方法?鉴于我们的Context不知道我们的数据类型(教师,学生),只知道它的接口(ITeacher,IStudent).
这样的事可以吗?
class Repository: IRepository
{
T Get<T>(int id) where T : EntityBase
{
var MyInterface = FindInterface<T>();
return Context.Get<MyInterface>(id);
}
}
Run Code Online (Sandbox Code Playgroud)
我想这会做:
class Repository: IRepository
{
IDataContext Context{get;set;}
T Get<T>(int id) where T : EntityBase
{
string[] interfaceList = new string[]
{ "ITeacher", "IStudent"};
Type interfaceType = null;
foreach (string s in interfaceList)
{
var types = typeof(T).FindInterfaces((x, y) => x.Name == y.ToString(), s);
if (types.Length > 0)
interfaceType = types[0];
}
if (interfaceType == null)
throw new Exception("Unknown Interface " + typeof(T).Name);
MethodInfo method = typeof(Context).GetMethod("Get");
MethodInfo generic = method.MakeGenericMethod(interfaceType);
var returnValue = generic.Invoke(Context, new object[] { id });
return (T)Convert.ChangeType(returnValue, typeof(T));
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:由于我不知道您的命名空间的名称,我已使用Name属性来过滤接口.在实际使用中,我建议您使用FullName以确保,如下所示:
...
string[] interfaceList = new string[]
{ "MyNamespace.ITeacher", "MyNamespace.IStudent"};
...
var types = typeof(T).FindInterfaces((x, y) => x.FullName == y.ToString(), s);
Run Code Online (Sandbox Code Playgroud)
我认为您可以通过在Context类上找到Get方法并将其作为对调用方提供的类型T的泛型调用来进行反射来完成此操作。我尚未对此进行测试,但是代码应如下所示:
T Get<T>(int id) where T : EntityBase
{
Type context = Context.GetType();
MethodInfo getMethod = context.GetMethod("Get", BindingFlags.Public);
MethodInfo genericGet = getMethod.MakeGenericMethod(new [] {typeof(T)});
return (T)genericGet.Invoke(Context, new object[] { id } );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15920 次 |
| 最近记录: |