假设我有以下内容:
图书馆计划:
interface IDoStuff
{
string DoThingOne<T>(T genericParm);
string DoThingOne<T>(T genericParm, int anotherParm);
string SendRequest<T>(IRequest<T> request);
}
interface IRequest<T>
{
T GenericParm { get; set; }
int IntParm { get; set; }
}
abstract class ThingDoerBase : IDoStuff
{
// simplifed but default for the integer parm
public virtual string DoThingOne<T>(T parm) => DoThingOne(parm, 25);
**// I want to make this virtual but because it has to new up a WebRequest defined in the other project it has to live there.**
public abstract string DoThingOne<T>(T parm; int anotherParm);
public abstract string SendRequest<T>(IRequest<T> request);
}
实施1项目
class Imp1Request<T> : IRequest<T>
{
public T GenericParm {get;set;}
public int IntParm {get;set;}
}
class ThingDoer : ThingDoerBase
{
public override string DoThingOne<T>(T parm, int anotherParm)
{
var req = new Imp1Request<T> { GenericParm = parm; IntParm = anotherParm };
return SendRequest(req);
}
public override string SendRequest<T>(IRequest<T> req)
{
// implementation for this guy is not important.
}
}
我想将抽象方法DoThingOne从抽象基类转换为调用抽象SendRequest的虚方法(类似于覆盖方法在实现中的作用)。
换句话说,我希望实现类中唯一的方法是SendRequest<T>(IRequest<T> req);
,其余方法在基类中。
我考虑过在图书馆项目中创建RequestBase : IRequest
;但是,为简洁起见,我在此省略的一件事是,IRequest的每个实现都需要不同的属性,我不想用它来污染库。例子是
Implement1
class Imp1Request<T> : IRequest<T>
{
[JsonProperty("_GenericParm")]
public T GenricParm {get;set;}
}
Implement2
class Imp2Request<T> : IRequest<T>
{
[XmlAttribute("StringParm")]
public T GenricParm {get;set;}
}
我认为工厂的做法是针对某些事情的,我只是在努力解决如何使其适应我的情况。
还有另一种方法来构建它吗?或者实现尽可能多的样板代码在基类中的目标?
答案 0 :(得分:1)
您可以将工厂注入 ThingDoerBase :
您的IRequest接口:
interface IRequest { }
interface IRequest<T>:IRequest
{
T GenericParm { get; set; }
int IntParm { get; set; }
}
你的基类:
abstract class ThingDoerBase : IDoStuff
{
private Func<IRequest> _factory;
protected ThingDoerBase(Func<IRequest> factory) => _factory = factory;
// simplifed but default for the integer parm
public virtual string DoThingOne<T>(T parm) => DoThingOne(parm, 25);
public virtual string DoThingOne<T>(T parm, int anotherParm)
{
if(!(_factory() is IRequest<T> request))
throw new InvalidOperationException();
request.GenericParm = parm;
request.IntParm = anotherParm;
return SendRequest(request);
}
public abstract string SendRequest<T>(IRequest<T> request);
public void ChangeRequestFactory(Func<IRequest> factory) => _factory = factory;
}
示例实施:
class Foo :ThingDoerBase{
public Foo(Func<IRequest> factory) : base(factory) { }
public override string SendRequest<T>(IRequest<T> request) =>
throw new NotImplementedException();
}
并测试:
var foo = new Foo(() => new Imp1Request<int>());
foo.DoThingOne(1);
foo.DoThingOne("lol"); //will throw InvalidOperationException
foo.ChangeRequestFactory(() => new Imp1Request<string>());
foo.DoThingOne(1);//will throw InvalidOperationException
foo.DoThingOne("lol");