【问题标题】:Wrapper class wrapping multiple types and composition pattern包装多种类型和组合模式的包装类
【发布时间】:2018-11-05 11:42:32
【问题描述】:

我有一个包装器类如下,它包装了 TypeA、TypeB 和 TypeC。

class Wrapper
{
    class TypeA {get;set;}
    class TypeB {get;set;}
    class TypeC{get;set;}
}

因此,现在调用者代码不好。因为我必须根据这样的不同类型来确定:

Wrapper wrapper = new Wrapper(TypeA);

if (wrapper.TypeA != null && wrapper.TypeA.SomeProperty != null)
{
    return wrapper.TypeA.SomeProperty;
}

if (wrapper.TypeB != null && wrapper.TypeB.SomeProperty != null)
{
    return wrapper.TypeB.SomeProperty;
}

Wrapper cwrapper = new Wrapper(TypeA, TypeB);

if (wrapper.TypeA == null && wrapper.TypeB != null && wrapper.TypeB.SomeProperty != null)
{
    return wrapper.TypeB.SomeProperty;
}

如您所见,调用者代码还必须检查 TypeA 和 TypeB 以及 TypeC 的大量组合。 我只是想使用一些组合并公开一些策略或属性,这将给我想要的对象,例如:

wrapper.As<TypeA>() 什么的。有什么建议可以避免调用者部分的多次检查吗?

【问题讨论】:

  • 可以同时包裹多个对象吗?
  • A、B、C 类型实现的接口相同吗?
  • 属性在每种类型中是否具有完全相同的名称。每种类型中的每个属性是否都有对应的属性?您需要像这样访问多少个属性?
  • 是的,它可以同时包装多个对象,并且它还有许多不同名称的其他属性。

标签: c# design-patterns composition


【解决方案1】:

为什么?您使用的是Adapter Pattern,您的班级应该看起来像

class Wrapper
{
    public TypeA A {get;set;}
    public TypeB B {get;set;}
    public TypeC C{get;set;}

  public Wrapper(TypeA A, TypeB B, TypeC C)
  {
   this.A = A;
   // rest initialization
  }
}

你现在可以说

Wrapper w = new Wrapper(new TypeA(), ...);
w.A.SomeProperty;

同样,您可以使用 Null Propagation 运算符来代替空值检查 if 条件

wrapper?.TypeA?.SomeProperty;

您可以一起使用 Null Coalesce 运算符,以便在属性为空的情况下返回属性的默认值

wrapper?.TypeA?.SomeProperty ?? string.Empty;

【讨论】:

    【解决方案2】:

    我建议在你的构造函数中使用一些保护子句和一些只读属性来整理所有这些

    class Wrapper
    {
        public TypeA A {get;}
        public TypeB B {get;}
        public TypeC C {get;}
    
      public Wrapper(TypeA A, TypeB B, TypeC C)
      {
       this.A = A ?? throw new ArgumentNullException(nameof(A));
       this.B = B ?? throw new ArgumentNullException(nameof(B));
       this.C = C ?? throw new ArgumentNullException(nameof(C));
      }
    }
    

    现在,除非有人对反射做了一些愚蠢的事情,否则您的 A、B、C 属性不能为空。所以你不需要空检查。

    然后您可以使用 null-coalescing 运算符来整理最后的位

    wrapper.A.someProperty ?? string.Empty
    

    【讨论】:

      【解决方案3】:

      就像你建议的那样,我会使用一种类型的强制转换方法。像这样的:

      class Wrapper {
          bool TryGet<T> (out T wrappedObj) {
              if (typeof(T) == ClassA.GetType()) {
                  wrappedObj = objA;
              }
              //...
              return wrappedObj != null;
          }
      
          // or
          bool TryGet<T,U>(Func<U> propGetter, out U prop) {
              if (TryGet<T>(out T wrappedObj)) {
                  prop = propGetter(wrappedObj);
                  return true;
              }
              prop = default(U); 
              return false;
          }
      }
      
      if (wrapper.TryGet<ClassA>(out ClassA obj)) {
      //...
      }
      
      //or
      
      if (wrapper.TryGet<ClassA, String>(aObj =>  aObj?.SomeProperty, out String prop) {
      
      }
      

      【讨论】:

        猜你喜欢
        • 2018-12-05
        • 2019-10-17
        • 1970-01-01
        • 1970-01-01
        • 2019-01-27
        • 1970-01-01
        • 2014-12-28
        • 2018-06-12
        • 2011-02-20
        相关资源
        最近更新 更多