C# SOLID - 在不违反 Open/Closed 的情况下扩展 class 和 override/hide 成员?
C# SOLID - Extend class and override/hide members without violating Open/Closed?
我需要扩展一个 class,子 class 将不使用父 class 的某些成员。应该如何处理未使用的成员并仍然遵守 open/closed SOLID 原则?我正在考虑做类似下面代码的事情,但是使用反射的现有代码会出现异常。如果我将数据放入已弃用的成员中,现有代码将产生意想不到的结果。
我觉得可能应该使用一种完全不同的方法。如何在不修改现有代码的情况下处理这种情况(这也违反了open/closed原则)?
class Parent
{
public virtual int myVarMin { get; set; } = 0;
public virtual int myVarMax { get; set; } = 10;
public int myVar { get; set; }
public int unchanged1 {get; set;}
//.
//numerous other members that are irrelevant to the question
//.
public void doSomething(){/*do something*/}
//
}
class Child:Parent
{
//considered impementation from original question
public override int myVarMin => throw new NotSupportedException();
public override int myVarMax => throw new NotSupportedException();
public List<int> myVarList = new List<int>();
}
class MyExistingCode
{
public void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent)}");
}
}
}
使用 Obsolete
属性通知开发人员您的方法已弃用,他们应该使用新版本。
[Obsolete("Method is deprecated, use Method2 please.")]
public void Method()
{
…
}
这里我更改了你的代码,所以使用反射你可以检测 method/property 是否被弃用,它不会再抛出异常。
public class Parent
{
public virtual int myVarMin { get; set; } = 0;
public virtual int myVarMax { get; set; } = 10;
public int myVar { get; set; }
}
public class Child : Parent
{
[Obsolete("Use other property")]
public override int myVarMin => throw new NotSupportedException();
[Obsolete("Use other property")]
public override int myVarMax => throw new NotSupportedException();
public List<int> myVarList = new List<int>();
}
class MyExistingCode
{
public void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
var customeAttributes = (ObsoleteAttribute[])info.GetCustomAttributes(typeof(ObsoleteAttribute), false);
if (customeAttributes.Length > 0)
{
Console.WriteLine($"{info.Name} is deprecated.");
}
else
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent)}");
}
}
}
}
我最终做了这样的事情(Parent
和MyExistingCode
类没有改变,所以它们符合open/closed原则:
class Child : Parent
{
public new int? myVarMin => null;
public new int? myVarMax => null;
public List<int> myVarList = new List<int>();
}
class MyNewCode : MyExistingCode
{
public new void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent) ?? "NULL"}");
}
}
}
令我惊讶的是,我可以毫无错误地用 int?
隐藏 int
。
如果更好,我会接受另一个答案。
我需要扩展一个 class,子 class 将不使用父 class 的某些成员。应该如何处理未使用的成员并仍然遵守 open/closed SOLID 原则?我正在考虑做类似下面代码的事情,但是使用反射的现有代码会出现异常。如果我将数据放入已弃用的成员中,现有代码将产生意想不到的结果。
我觉得可能应该使用一种完全不同的方法。如何在不修改现有代码的情况下处理这种情况(这也违反了open/closed原则)?
class Parent
{
public virtual int myVarMin { get; set; } = 0;
public virtual int myVarMax { get; set; } = 10;
public int myVar { get; set; }
public int unchanged1 {get; set;}
//.
//numerous other members that are irrelevant to the question
//.
public void doSomething(){/*do something*/}
//
}
class Child:Parent
{
//considered impementation from original question
public override int myVarMin => throw new NotSupportedException();
public override int myVarMax => throw new NotSupportedException();
public List<int> myVarList = new List<int>();
}
class MyExistingCode
{
public void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent)}");
}
}
}
使用 Obsolete
属性通知开发人员您的方法已弃用,他们应该使用新版本。
[Obsolete("Method is deprecated, use Method2 please.")]
public void Method()
{
…
}
这里我更改了你的代码,所以使用反射你可以检测 method/property 是否被弃用,它不会再抛出异常。
public class Parent
{
public virtual int myVarMin { get; set; } = 0;
public virtual int myVarMax { get; set; } = 10;
public int myVar { get; set; }
}
public class Child : Parent
{
[Obsolete("Use other property")]
public override int myVarMin => throw new NotSupportedException();
[Obsolete("Use other property")]
public override int myVarMax => throw new NotSupportedException();
public List<int> myVarList = new List<int>();
}
class MyExistingCode
{
public void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
var customeAttributes = (ObsoleteAttribute[])info.GetCustomAttributes(typeof(ObsoleteAttribute), false);
if (customeAttributes.Length > 0)
{
Console.WriteLine($"{info.Name} is deprecated.");
}
else
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent)}");
}
}
}
}
我最终做了这样的事情(Parent
和MyExistingCode
类没有改变,所以它们符合open/closed原则:
class Child : Parent
{
public new int? myVarMin => null;
public new int? myVarMax => null;
public List<int> myVarList = new List<int>();
}
class MyNewCode : MyExistingCode
{
public new void Display(Parent parent)
{
foreach (var info in parent.GetType().GetProperties())
{
Console.WriteLine($"{info.Name}: {info.GetValue(parent) ?? "NULL"}");
}
}
}
令我惊讶的是,我可以毫无错误地用 int?
隐藏 int
。
如果更好,我会接受另一个答案。