在通用方法中返回接口继承的类

时间:2018-07-20 04:14:31

标签: c# generics inheritance

我有3个非常相似的对象,只有几个区别

public class Person
{
    public Person(ResourceObject resource)
    {
        // resource comes from an API provided by one
        // of our systems (i have no control over it)
        this.ResourceObject = resource;
    }

    // Resource
    internal ResourceObject ResourceObject { get; }

    // Similar properties
    public string ObjectID { get; }
    public string ObjectType { get; }
    public IEnumerable<string> PropertyNames { get; }

    // Person-specific property example - Organisation
    public string Organisation { get; set; }
}

public class Computer
{
    public Computer(ResourceObject resource)
    {
        // resource comes from an API provided by one
        // of our systems (i have no control over it)
        this.ResourceObject = resource;
    }

    // Resource
    internal ResourceObject ResourceObject { get; }

    // Similar properties
    public string ObjectID { get; }
    public string ObjectType { get; }
    public IEnumerable<string> PropertyNames { get; }

    // Computer-specific property example - OperatingSystem
    public string OperatingSystem { get; set; }
}

public class Group
{
    public Group(ResourceObject resource)
    {
        // resource comes from an API provided by one
        // of our systems (i have no control over it)
        this.ResourceObject = resource;
    }

    // Resource
    internal ResourceObject ResourceObject { get; }

    // Similar properties
    public string ObjectID { get; }
    public string ObjectType { get; }
    public IEnumerable<string> PropertyNames { get; }

    // Group-specific property example - Members
    public string Members { get; set; }
}

我目前有GetPersonGetComputerGetGroup方法有效,但是它们本质上是做同样的事情,然后调用特定的对象构造函数之一。为了深入了解泛型和接口的世界并了解更多(与您一样),我尝试创建一种GetResource<T>方法,该方法与这3种方法的工作相同,而没有所有重复的代码。

我创建了IResource界面来标识常用属性:

public interface IResource
{
    string ObjectID { get; }
    string ObjectType { get; }
    IEnumerable<string> PropertyNames { get; }
}

,然后尝试创建GetResource<T>方法,但被返回代码卡住了:

    public static T GetResource<T>(string identity) where T : IResource
    {
        // get resource from system API

        // and then return T somehow?
        return new T(resourceObject);
    }

我曾考虑将返回值从T更改为IResource,但是我仍然不确定如何确定要返回的类(也许我需要基类?Resource也许)。

在这种情况下,我选择泛型的原因是,如果系统API更新并且突然有了一个新的Location对象,我不想创建一个GetLocation方法,然后又有4个对象除了一行代码外,它们的功能完全相同。

这是泛型的正确用例吗?如果可以,我的方法如何找出要返回的对象?

1 个答案:

答案 0 :(得分:2)

使用基类来保持常见行为。

public abstract class Resource {

    protected Resource (ResourceObject resource) {
        // resource comes from an API provided by one
        // of our systems (i have no control over it)
        this.ResourceObject = resource;
    }

    // Resource
    internal ResourceObject ResourceObject { get; }

    // Similar properties
    public string ObjectID { get; }
    public string ObjectType { get; }
    public IEnumerable<string> PropertyNames { get; }
}

派生类

public class Person : Resource {

    public Person(ResourceObject resource):base(resource){
    }

    // Person-specific property example - Organisation
    public string Organisation { get; set; }
}

public class Computer : Resource {
    public Computer(ResourceObject resource) : base(resource) {
    }

    // Computer-specific property example - OperatingSystem
    public string OperatingSystem { get; set; }
}

public class Group : Resource {

    public Group(ResourceObject resource) : base(resource) {
    }

    // Group-specific property example - Members
    public string Members { get; set; }
}

接口无法初始化,因此尝试传递构造函数参数将无效。

有了基类约束,通用方法变为

public static T GetResource<T>(string identity) where T : Resource {
    // get resource from system API

    // and then return T somehow?
    return (T) Activator.CreateInstance(typeof(T), resourceObject);
}

二手

Person person = GetResource<Person>("person_identity");