0

我得到了两个库,每个库都有自己的命名空间,它们对于 api 的请求部分具有相同的类结构,但响应不同。

我想编写一个函数来处理与其命名空间类型无关的两个请求(我已经尝试过泛型,但未能创建解决方案)。

这是我正在尝试做的一个例子:

public void Function1()
{
    Namespace1.MyType type1 = new Namespace1.MyType1();
    type1.InnerType = new Namespace1.MyType2();

    type1.PerformMethod1();
}

public void Function2()
{
    Namespace2.MyType type1 = new Namespace2.MyType1();
    type1.InnerType = new Namespace2.MyType2();

    type1.PerformMethod1();
}

我尝试通过以下方式在方法级别使用泛型:

public void Function1<TType1, TType2>() 
    where TType1: NamesSpace1.Type1, NamesSpace2.Type1, new() 
    where TType2: Namespace1.Type2. Namespace2.Type2(), new()
{
    TType1 type1 = new TType1();
    type1.InnerType = new TType2();

    type1.PerformMethod1();
}

但是,.net 不允许对泛型进行这种级别的限制。关于如何创建通用函数的任何建议都会很棒。

谢谢

4

2 回答 2

2

简短的回答是:你不能。

C#(或.NET)不支持“结构子类型”,这使得这两个类完全分开,尽管它们具有相同的成员。

但是,您可以使用dynamic关键字,但您将失去所有编译时类型安全性。

publiv void Function(dynamic type1)
{
    type1.PerformMethod1();
}

您仍然必须创建 and 的两个不同实例type1type2因此在这里您并没有真正获得太多收益。

另一种具有基本相同缺点的可能解决方案是使用反射来创建类型:

public void Function(string assemblyName, string namespace)
{
    var type1Name = namespace + ".Type1, " + assemblyName;
    var type2Name = namespace + ".Type2, " + assemblyName;
    dynamic type1 = Activator.CreateInstance(Type.GetType(type1Name));
    dynamic type2 = Activator.CreateInstance(Type.GetType(type1Name));
    type1.InnerType = type2;
    type1.PerformMethod1();
}

第三种解决方案是仅使用带有new()约束的泛型,以便能够更轻松地创建实例并使用运行时类型检查来确保只使用了允许的类型。同样,这与其他两个解决方案具有相同的缺点: 没有编译时类型安全:

public void Function1<TType1, TType2>() 
    where TType1 : new() 
    where TType2 : new()
{
    if(typeof(TType1) != typeof(Namespace1.MyType1) || 
       typeof(TType1) != typeof(Namespace2.MyType1) || 
       typeof(TType2) != typeof(Namespace1.MyType2) || 
       typeof(TType2) != typeof(Namespace2.MyType2))
        throw new ArgumentException(...); 

    // .NET 4:
    dynamic type1 = new TType1();
    dynamic type2 = new TType2();
    // Pre .NET 4:
    // var type1 = new TType1();
    // var type2 = new TType2();

    // .NET 4:
    type1.InnerType = type2;
    // Pre .NET 4:
    // type1.GetType().GetProperty("InnerType").SetValue(type1, type2);

    // .NET 4:
    type1.PerformMethod1();
    // Pre .NET 4:
    // type1.GetType().GetMethod("PerformMethod1").Invoke(type1, new object[0]);
}
于 2013-02-21T11:45:58.490 回答
1

.Net 中的泛型确实不是这样工作的。

我认为最好的方法是创建一个通用接口并以某种方式融入库类。问题是如何做到这一点。

如果所讨论的类型不是密封的并且您自己创建它的实例,那么您可以创建一个实现此接口的派生类,该接口将由继承的方法自动实现:

interface IMyType
{
    object InnerType { get; set; }
    void PerformMethod1();
}

class Namespace1MyTypeWithInterface : Namespace1.MyType, IMyType
{}

这假设这两种类型实际上是相同的。例如,如果InnerType每个的类型不同,情况就会变得更加复杂。解决该问题的一种方法是使接口在属性类型中具有通用性。

如果以前的解决方案不适合您,那么您可以为每个命名空间创建适配器类。两个适配器将再次共享相同的接口,并将每次调用委托给实际类型的实例。

class Namespace1MyTypeAdapter : IMyType
{
    private readonly Namespace1.MyType m_adapted;

    public Namespace1MyTypeAdapter(Namespace1.MyType adapted)
    {
        m_adapted = adapted;
    }

    public object InnerType
    {
        get { return m_adapted.InnerType; }
        set { m_adapted.InnerType = value; }
    }

    public void PerformMethod1()
    {
        m_adapted.PerformMethod1();
    }
}

这是很多重复的代码,但你只写一次,然后你就可以以同样的方式使用这两个类。

还有一种选择是使用dynamic或反射。

于 2013-02-21T12:01:07.743 回答