我知道这之前已经涵盖过,但我还没有找到任何好的解决方案。 在示例中,我使用两个返回类型类(ClassA 和 ClassB(和一个返回 args 类。我有一个基类,我的 ClassXml 和 ClassText 从中扩展,并希望阻止打印中的特定接口转换。这可能吗?
调用 ClassXml 和 ClassText Execute 方法,这些方法又调用调用相应打印的基类功能。
using System;
namespace ConsoleApplication1
{
internal class Program
{
public class ClassA
{
public string Xml
{
get { return "xml"; }
}
}
public class ClassB
{
public char Text
{
get { return 't'; }
}
}
public interface IReturnArgs<out T>
{
string Name { get; set; }
T Source { get; }
}
public class ReturnArgs<T> : IReturnArgs<T>
where T : class
{
public string Name { get; set; }
private T _source;
public T Source
{
get { return _source ?? (_source = (T) Activator.CreateInstance(typeof (T), new object[] {})); }
}
}
private static void Main(string[] args)
{
var classA = new ReturnArgs<ClassA>();
var classB = new ReturnArgs<ClassB>();
var xml = new ClassXml();
xml.Execute(classA);
var text = new ClassText();
text.Execute(classB);
Console.ReadKey();
}
public abstract class ClassBase
{
public void Execute(IReturnArgs<object> args)
{
// Do something common to both classes e.g. run tasks etc (not shown)
// calls print when completed, each call specific to child class.
Print(args);
}
/// <summary>
/// Abstract print method. Print invokes the child implementation.
/// </summary>
/// <param name="args"></param>
public virtual void Print(IReturnArgs<object> args){}
}
public class ClassXml : ClassBase
{
public void Execute(IReturnArgs<ClassA> args)
{
//invoked externally (Main) calling base common functionality.
base.Execute(args);
Print(args);
}
//print invoked by child class call - Note if invoked in this class then IReturnArgs<ClassA> could be used
//and a cast would not be necessary - however, this would separate common calls accross child classes.
public void Print(IReturnArgs<ClassA> args)
{
Console.WriteLine("ClassA Source {0}", ((IReturnArgs<ClassA>)args).Source.Xml);//ugly cast
}
}
public class ClassText : ClassBase
{
public void Execute(IReturnArgs<ClassB> args)
{
//invoked externally (Main) calling base common functionality.
base.Execute(args);
}
//print invoked by base class call which requires the cast IReturnArgs<ClassB> from IReturnArgs<object>
public override void Print(IReturnArgs<object> args)
{
Console.WriteLine("ClassB Source {0}", ((IReturnArgs<ClassB>)args).Source.Text);//ugly cast
}
}
}
}
你似乎在做同样的事情两次。
ClassA
和ClassB
与ClassXML
和ClassText
的关系太强了。
要解决此问题,您可以将ClassXML
的功能放在ClassA
中,将ClassText
的功能放在ClassB
中。
或者,您可以使用方法 GetContent())
实现类似 ToString()
或其他接口(ITextContent
的东西来分别返回 XML 和文本。这样,您只需要一个只调用ITextContent.GetContent()
的ClassContent
类。
完整的示例:
using System;
namespace ConsoleApplication1
{
internal class Program
{
public Interface ITextContent
{
string GetContent();
}
public class ClassA : ITextContent
{
public string Xml
{
get { return "xml"; }
}
public string GetContent()
{
return this.Xml;
}
}
public class ClassB : ITextContent
{
public char Text
{
get { return 't'; }
}
public string GetContent()
{
return this.Text;
}
}
public interface IReturnArgs<out T>
{
string Name { get; set; }
T Source { get; }
}
public class ReturnArgs<T> : IReturnArgs<T>
where T : class
{
public string Name { get; set; }
private T _source;
public T Source
{
get { return _source ?? (_source = (T) Activator.CreateInstance(typeof (T), new object[] {})); }
}
}
private static void Main(string[] args)
{
var classA = new ReturnArgs<ClassA>();
var classB = new ReturnArgs<ClassB>();
var xml = new ClassContent();
xml.Execute(classA);
var text = new ClassContent();
text.Execute(classB);
Console.ReadKey();
}
public class ClassContent
{
public void Execute(IReturnArgs<object> args)
{
Print(args);
}
public void Print(IReturnArgs<object> args)
{
Console.WriteLine(((IReturnArgs<ITextContent>)args).GetContent());
}
}
}
}
您确实不应该面临在子类中进行强制转换的问题,因为基类不应该定义其参数类型依赖于子类的方法。基类应该是两者的公共接口,这意味着无论我分配给b
和args
什么,这都应该始终有效:
ClassBase b;
IReturnArgs<object> args;
...
b.Print(args);
但是对于您的类,例如,如果我使用 ClassText
和 IReturnArgs<ClassA>
,它将失败。
为什么不使用通用基础?
public abstract class ClassBase<T> {
public void Execute(IReturnArgs<T> args) { ... }
public virtual void Print(IReturnArgs<T> args) { ... }
}
public class ClassXml : ClassBase<ClassA> {
public override void Print(IReturnArgs<ClassA> args) {
Console.WriteLine("ClassA Source {0}", args.Source.Text);
}
}