如何通过泛型类型获得接口的具体实现?

DDi*_*ita 4 c# reflection

我需要一些帮助来弄清楚如何使用反射来获得基于Dto类型的具体实现:

public interface IDocumentService<TDto>
{
}

public interface ICommentService: IDoumentService<CommentDto>
{
}

public abstract class DocumentService<TEntity,TDto>: IDocumentService<TDto> where TEntity: Entity, where TDto: Dto
{
}

public class CommentService: DocumentService<Comment,CommentDto>, ICommentService
{
}
Run Code Online (Sandbox Code Playgroud)

所以,我想要做的是将CommentDto传递给方法,以便我可以访问CommentService.

public IDocumentService<TDto> GetDocumentService<TDto>()
{
    //based on the TDto type I want to find the concrete that 
    //implements IDocumentService<TDto>
}
Run Code Online (Sandbox Code Playgroud)

我会这样称呼它:

var commentDocumentService = GetDocumentService<CommentDto>();
Run Code Online (Sandbox Code Playgroud)

所以,我会回到CommentService,知道我只会看到IDocumentService接口的方法部分.

Pet*_* O. 7

以下是GetDocumentService的可能实现.

    public static IDocumentService<TDto> GetDocumentService<TDto>()
    {
        // Gets the type for IDocumentService
        Type tDto=typeof(IDocumentService<TDto>);
        Type tConcrete=null;
        foreach(Type t in Assembly.GetExecutingAssembly().GetTypes()){
            // Find a type that implements tDto and is concrete.
            // Assumes that the type is found in the executing assembly.
            if(tDto.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface){
                tConcrete=t;
                break;
            }
        }
        // Create an instance of the concrete type
        object o=Activator.CreateInstance(tConcrete);
        return (IDocumentService<TDto>)o;
    }
Run Code Online (Sandbox Code Playgroud)

目前尚不清楚你是否想要返回一个新对象,所以我这么认为.

编辑:

由于您的评论,这里是GetDocumentService的修改版本.缺点是您需要指定另一个类型参数.但是,优点是这种方法提供了一定程度的类型安全性,因为两种类型参数必须兼容.

    public static T GetDocumentService<TDto, T>() where T : IDocumentService<TDto>
    {
        // Gets the type for IDocumentService
        Type tDto=typeof(T);
        Type tConcrete=null;
        foreach(Type t in Assembly.GetExecutingAssembly().GetTypes()){
            // Find a type that implements tDto and is concrete.
            // Assumes that the type is found in the calling assembly.
            if(tDto.IsAssignableFrom(t) && !t.IsAbstract && !t.IsInterface){
                tConcrete=t;
                break;
            }
        }
        // Create an instance of the concrete type
        object o=Activator.CreateInstance(tConcrete);
        return (T)o;
    }
Run Code Online (Sandbox Code Playgroud)

编辑2:

如果我理解正确,您希望通过GetDocumentService的返回值类型实现其他接口.例如,GetDocumentService<CommentDto>返回CommentService实现ICommentService接口的类型的对象.如果我理解正确,返回值应该是Type对象(例如,返回值可以是typeof(ICommentService)).获得类型后,应调用类型的FullName属性以获取类型的名称.

例如,在返回值上使用以下方法GetDocumentService来获取该值实现的接口类型typeof(ICommentService).

    public static Type GetDocumentServiceType<TDto>(IDocumentService<TDto> obj){
        Type tDto=typeof(IDocumentService<TDto>);
        foreach(Type iface in obj.GetType().GetInterfaces()){
            if(tDto.IsAssignableFrom(iface) && !iface.Equals(tDto)){
                return iface;
            }
        }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)