我有一个如下的包装器类,用于包装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>()
之类的。有什么建议可以避免调用方进行多次检查吗?
答案 0 :(得分:2)
为什么?您使用的是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 运算符,以在属性为null的情况下返回属性的默认值
wrapper?.TypeA?.SomeProperty ?? string.Empty;
答案 1 :(得分:0)
我建议您在构造函数中使用一些保护子句,并使用一些只读属性来整理所有内容
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。因此,您无需进行空检查。
然后您可以使用null运算符来整理最后几位
wrapper.A.someProperty ?? string.Empty
答案 2 :(得分:0)
就像您建议的那样,我将使用一种强制转换方法。像这样:
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) {
}