c# Factory for concrete implementation of generic base class - c#

I have a Base class which is generic.
I have a concrete class which implements the base class.
How would I create a factory class/method for delivering different types of concrete classes?
Here an example:
public class ReceiverBase<T>
where T : IInterpreter
{ ... }
public class SpecialReceiver : ReceiverBase<OwnInterpreter> { ... }
public class ReceiverFactory<T>
where T : ReceiverBase<IInterpreter>, new()
public T Create(string type) {
switch(type) {
default:
return new SpecialReceiver();
}
}
}
The problem is that ReceiverBase seems not to be possible because the compiler only wants classes as Constraints, not interfaces.
And the second problem is that I cannot convert SpecialReceiver to T.
So is there a way to get this working?
=== EDIT: Added example according to first answer ===
public interface IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
public void Dispose()
{
throw new NotImplementedException();
}
public void DoSomething() { }
}
public abstract class ReceiverBase<T>
where T : IInterpreter
{
public T MyReceiver { get; set; }
internal abstract void Start();
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter, new()
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
MyReceiver = new T();
}
}
public class ReceiverFactory<T>
where T : IInterpreter, new()
{
public static ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The Problem is: MyReceiver.DoSomething(); will not work.
Additionally I would have to call the factory like this: ReceiverFactory<OwnInterpreter>.Create(""); I'd like to have it that way: ReceiverFactory.Create("SpecialReceiver");

You can use generic method in your factory:
class Program
{
static void Main(string[] args)
{
var own = ReceiverFactory.Create<OwnInterpreter>();
var other = ReceiverFactory.Create<OtherInterpreter>();
own.Start();
other.Start();
Console.ReadLine();
}
}
interface IInterpreter
{
void DoSomething();
}
class OwnInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Own"); }
}
class OtherInterpreter : IInterpreter
{
public void DoSomething() { Console.WriteLine("Other"); }
}
abstract class ReceiverBase<T> where T: IInterpreter, new()
{
public T Interpreter { get; set; }
public ReceiverBase()
{
Interpreter = new T();
}
public void Start()
{
Interpreter.DoSomething();
}
}
class SpecialReceiver : ReceiverBase<OwnInterpreter> { }
class OtherReceiver : ReceiverBase<OtherInterpreter> { }
static class ReceiverFactory
{
private static Dictionary<string, object> factories = new Dictionary<string, object>();
static ReceiverFactory()
{
RegisterFactory(() => new SpecialReceiver());
RegisterFactory(() => new OtherReceiver());
}
public static void RegisterFactory<T>(Func<ReceiverBase<T>> factory) where T : IInterpreter, new()
{
factories.Add(typeof(T).FullName, factory);
}
public static ReceiverBase<T> Create<T>() where T : IInterpreter, new()
{
var type = typeof(T);
return ((Func<ReceiverBase<T>>)factories[type.FullName]).Invoke();
}
}
In fact, you do not need "new()" constraint here, since you use factories.

I suggest you to change your code to:
public class ReceiverBase<T> where T : IInterpreter
{
}
public interface IInterpreter
{
}
public class SpecialReceiver<T> : ReceiverBase<T>
where T : IInterpreter
{
}
public class OwnInterpreter : IInterpreter
{
}
public class ReceiverFactory<T> where T : IInterpreter, new()
{
public ReceiverBase<T> Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver<T>();
}
}
}
The reason why you cannot just return T in your case is, that there is no implicit conversion between SpecialReceiver and ReceiverBase<IInterpreter>.

I was able to find a solution which suits my needs.
I've added another interface IReciver which defines the properties and members I really need. The factory method returns IReceiver so I can omit all binding issues whith generics. Sometimes it is just that easy. :)
public interface IInterpreter { }
public interface IReceiver
{
bool Enabled { get; set; }
}
public class OwnInterpreter : IInterpreter
{
public void DoSomething() { }
}
public abstract class ReceiverBase<T> : IReceiver
where T : IInterpreter, new()
{
public T MyReceiver { get; set; }
internal abstract void Start();
private bool _isEnabled;
public bool Enabled { get { return _isEnabled; } set { _isEnabled = value; OnEnable(value); } }
internal abstract void OnEnable(bool isEnabled);
protected ReceiverBase()
{
MyReceiver = new T();
}
}
public class SpecialReceiver : ReceiverBase<OwnInterpreter>
{
public void CheckSomething()
{
MyReceiver.DoSomething();
}
internal override void Start()
{
// just for testing puropses
MyReceiver = new OwnInterpreter();
}
internal override void OnEnable(bool isEnabled)
{
MyReceiver = isEnabled ? new OwnInterpreter() : null;
}
}
public class ReceiverFactory
{
public static IReceiver Create(string type)
{
switch (type)
{
default:
return new SpecialReceiver();
}
}
}
public class Program
{
[STAThread]
public static void Main()
{
ReceiverFactory.Create("");
}
}

Related

Extract Reusable Code into Abstract Base Class with Generic Parameters

I am trying to achieve a design in c# like below.
void Main()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped(typeof(RedisRepository<>));
serviceCollection.AddScoped(typeof(CommitterBase<IDto>), typeof(ACommitter));
serviceCollection.AddScoped(typeof(CommitterBase<IDto>), typeof(BCommitter));
serviceCollection.AddScoped<Client>();
var services = serviceCollection.BuildServiceProvider();
var client = services.GetRequiredService<Client>();
client.Dump();
}
public class RedisRepository<T> where T: IDto
{
public void Add(T dto)
{
Console.WriteLine("Added data");
}
}
public interface IDto
{
}
public class ADto: IDto
{
}
public class BDto : IDto
{
}
and :
public abstract class CommitterBase<T> where T: IDto
{
public CommitterBase(RedisRepository<T> repo)
{ }
public void Commit()
{
var dto = GenerateDto();
//do something with dto here
}
protected abstract T GenerateDto();
}
and its implementations:
public class ACommitter : CommitterBase<ADto>
{
public ACommitter(RedisRepository<ADto> repo): base(repo)
{ }
protected override ADto GenerateDto()
{
return new ADto();
}
}
public class BCommitter : CommitterBase<BDto>
{
public BCommitter(RedisRepository<BDto> repo) : base(repo)
{
}
protected override BDto GenerateDto()
{
return new BDto();
}
}
public class Client
{
public Client(IEnumerable<CommitterBase<IDto>> committers)
{ }
}
error that I get
Implementation type 'BCommitter' can't be converted to
service type 'UserQuery+CommitterBase`1[IDto]'
I understand from this stackoverflow post that this error is expected. Just wondering how to achieve similar effect without encountering the error. My aim is to extract reusable code into an Abstract Base Class and let the implementations do bare minimum.
Thanks in advance!
Interface cannot be instantiated and IDto is interface. So you can register specific implementation to your interface.
I little bit refactored code to use generic parameters.
This is yor base abstract class:
public abstract class CommitterBase<T> where T : IDto
{
public CommitterBase(RedisRepository<T> repo)
{ }
public void Commit()
{
var dto = GenerateDto();
//do something with dto here
}
protected abstract T GenerateDto();
}
And its concrete implementations such as ACommitter:
public class ACommitter<T> : CommitterBase<T> where T : IDto, new()
{
public ACommitter(RedisRepository<T> repo) : base(repo)
{ }
protected override T GenerateDto()
{
return new T();
}
}
and BCommitter:
public class BCommitter<T> : CommitterBase<T> where T: IDto, new()
{
public T FooBar { get; set; }
public BCommitter(RedisRepository<T> repo) : base(repo)
{
}
protected override T GenerateDto()
{
return new T();
}
}
and RedisRepository:
public class RedisRepository<T> where T : IDto
{
public void Add(T dto)
{
Console.WriteLine("Added data");
}
}
and Client class:
public class Client<T> where T : IDto, new()
{
public CommitterBase<T> CommitterBaseProperty { get; set; }
public Client(CommitterBase<T> committer) // if you want all instances of committers,
// then you need to create a factory
// and inject it through DI
{
CommitterBaseProperty = committer;
}
}
And you can call it like this:
static void Main(string[] args)
{
ServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<RedisRepository<ADto>>();
serviceCollection.AddScoped<RedisRepository<BDto>>();
serviceCollection.AddScoped<CommitterBase<ADto>, ACommitter<ADto>>();
serviceCollection.AddScoped<CommitterBase<BDto>, BCommitter<BDto>>();
serviceCollection.AddScoped<Client<ADto>>();
ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
CommitterBase<ADto> committerBase = serviceProvider.GetRequiredService<CommitterBase<ADto>>();
CommitterBase<BDto> committerBase_B =
serviceProvider.GetRequiredService<CommitterBase<BDto>>();
committerBase.Commit();
Client<ADto> client = serviceProvider.GetRequiredService<Client<ADto>>();
}

Head First design pattern program in C# -getting Duck.quackableDuck is inaccessible

I am getting runtime error Duck.quackableDuck and Duck.flyableDuck is inaccessible.
I have created two interfaces FlyableDuck and QuackableDuck. Class MallardDuck is inherited from class Duck.
using System;
//creating interfaces
public interface FlyableDuck
{
void fly();
}
public interface QuackableDuck
{
void quack();
}
//creating behavior classes
public class FlyWithWings:FlyableDuck
{
public void fly()
{
Console.WriteLine("I am flying.");
}
}
public class FlyNoWings: FlyableDuck
{
public void fly()
{
Console.WriteLine("I can't fly. :(");
}
}
public class Quacking: QuackableDuck
{
public void quack()
{
Console.WriteLine("Quack Quack!!");
}
}
public class NoQuack : QuackableDuck
{
public void quack()
{
Console.WriteLine("Can't quack :(");
}
}
public class SqueakQuack : QuackableDuck
{
public void quack()
{
Console.WriteLine("Squeak quack!!");
}
}
//creating abstrack class
public abstract class Duck
{
QuackableDuck quackableDuck;
FlyableDuck flyableDuck;
public Duck() { }
public abstract void display();
public void perfomFly()
{
flyableDuck.fly();
}
public void perfomQuack()
{
quackableDuck.quack();
}
public void swim()
{
Console.WriteLine("All ducks swim :)");
}
}
//subclass
public class MallardDuck:Duck
{
public MallardDuck()
{
quackableDuck = new Quacking();
flyableDuck = new FlyWithWings();
}
public override void display()
{
Console.WriteLine("I am Mallard Duck.");
}
}
public class Class2
{
public static void Main(String[] args)
{
MallardDuck mallard = new MallardDuck();
mallard.perfomFly();
mallard.perfomQuack();
Console.ReadKey();
}
}
These 2:
QuackableDuck quackableDuck;
FlyableDuck flyableDuck;
Are private (by default) so change it to:
public QuackableDuck quackableDuck;
public FlyableDuck flyableDuck;
You can also use protected/internal instead of public

Ninject contextual binding for 2+ dependent classes w/ different names for same constructor param

Having trouble figuring out how to manage contextual binding in the scenario where two classes have the same underlying interface dependency, but each class ctor's parameter is named differently. Pseudo code below to demonstrate my situation:
interface IThing { }
public class Thing1 : IThing { public Thing1(string fileCode) { } }
public class Thing2 : IThing { public Thing2(string fileCode) { } }
interface IThingFactory { IThing CreateThing(string fileCode); }
interface IDependentThing { }
public class A : IDependentThing { public A(string fileCode, IThingFactory thingFactory) { } }
public class B : IDependentThing { public B(string fileCd, IThingFactory thingFactory) { } } //How to handle binding for this dependent?
interface IDependentThingFactory { IDependentThing CreateDependentThing(string fileCode); }
//...
public override void Load()
{
Bind<IThing>().ToMethod(ctx =>
{
var fileCode = ctx.Parameters.First(p => p.Name == "fileCode").GetValue(ctx, null) as string;
IThing thing = null;
if (fileCode == "FileType1")
{
Bind<Thing1>().ToSelf().WithConstructorArgument("fileCode", fileCode);
thing = Kernel.Get<Thing1>();
}
else if (fileCode == "FileType2")
{
Bind<Thing2>().ToSelf().WithConstructorArgument("fileCode", fileCode);
thing = Kernel.Get<Thing2>();
}
return thing;
});
Bind<IThingFactory>().ToFactory();
Bind<IDependentThingFactory>().ToFactory();
}
//Later...
using (TextReader tr = new StreamReader(path))
{
string firstLine = tr.ReadLine();
if (firstLine.Substring(838, 1) == ".")
{
fileCode = "FileType1";
}
else if (firstLine.Substring(883, 1) == ".")
{
fileCode = "FileType2";
}
//won't work for creating B
Kernel.Get<IDependentThing>(new ConstructorArgument("fileCode", fileCode));
//or maybe...
//seems to eliminate my problem by allowing me to handle variations
//in parameter names from within A and B's ctors, but looks like it
//requires injecting factories along the chain (see A & B ctor arguments).
dependentThingFactory.CreateDependentThing(fileCode)
};
fileCode is computed based off of some analysis of local files. Once the type of file is determined, I want Ninject to hand back the appropriate object for processing that file
How would I handle the binding for B since the existing binding I defined requires a constructor parameter with a different name? Is there a better way to do this in general?
I guess I could just use p.Name == "fileCode" || p.Name == "fileCd", but I can't shake the feeling that I'm doing something wrong (feels messy). Also, I'm not thrilled about pulling parameters by name, and I've thought about maybe creating a custom type that would give Ninject something more concrete to match against versus a string parameter. From where I'm standing it looks like I either just manage the multiple parameter names situation, or switch to custom types as my parameters instead of strings.
Making parameter injection more refactor safe and making them available for the whole resolution context
Instead of "named parameters" you can use a "type matching" or "typed" parameter. The factories IInstanceProvider can be exchanged for another one which does so:
kernel.Bind<IThingFactory>()
.ToFactory(() => new TypeMatchingArgumentInheritanceInstanceProvider());
Note:
this IInstanceProvider will also make the argument available further "downstream" (it "inherits" the parameter)
a string is very verbose so you may want to choose to wrap it in another type, like class ConnectionInfo.
Contextual Binding combined with parameter injection
So let's say we create our own FileType type to be more verbose than just using string:
public class FileCode
{
public FileCode(string value)
{
Value = value;
}
public string Value { get; private set; }
}
(maybe you want to replace that with an enum?)
Since your requirements are more complex we're going to have to change things up a little bit.
We're going to create our own IConstructorArgument to easily be able to match it for When-contextual bindings and also inject it's value based on type-matching (as above):
internal class FileCodeParameter : IConstructorArgument
{
private readonly FileCode fileCode;
public FileCodeParameter(FileCode fileCode)
{
this.fileCode = fileCode;
}
public string Name { get { return "File Code Parameter"; } }
public bool ShouldInherit { get { return true; } }
public FileCode FileCode { get { return this.fileCode; } }
public bool Equals(IParameter other)
{
var otherFileCodeParameter = other as FileCodeParameter;
if (otherFileCodeParameter == null)
{
return false;
}
return otherFileCodeParameter.fileCode == this.fileCode;
}
public object GetValue(IContext context, ITarget target)
{
return this.fileCode;
}
public bool AppliesToTarget(IContext context, ITarget target)
{
return target.Type == typeof(FileCode);
}
}
Now let me create some sample codes so we can later verify that it works:
public interface IThing
{
FileCode FileCode { get; }
}
public abstract class Thing : IThing
{
protected Thing(FileCode fileCode)
{
FileCode = fileCode;
}
public FileCode FileCode { get; private set; }
}
public class ThingFoo : Thing
{
public ThingFoo(FileCode fileCode) : base(fileCode) { }
}
public class ThingBar : Thing
{
public ThingBar(FileCode fileCode) : base(fileCode) { }
}
public interface IOtherThing
{
FileCode FileCode { get; }
}
public abstract class OtherThing : IOtherThing
{
protected OtherThing(FileCode fileCode)
{
FileCode = fileCode;
}
public FileCode FileCode { get; private set; }
}
public class OtherThingFoo : OtherThing
{
public OtherThingFoo(FileCode fileCode) : base(fileCode) { }
}
public class OtherThingBar : OtherThing
{
public OtherThingBar(FileCode fileCode) : base(fileCode) { }
}
public class OtherThingWrapper
{
public OtherThingWrapper(IOtherThing otherThing)
{
OtherThing = otherThing;
}
public IOtherThing OtherThing { get; private set; }
}
public class FileProcessor
{
public FileProcessor(IThing thing, OtherThingWrapper otherThingWrapper)
{
Thing = thing;
OtherThingWrapper = otherThingWrapper;
}
public IThing Thing { get; private set; }
public OtherThingWrapper OtherThingWrapper { get; private set; }
}
What's missing? The factory. We could use the ToFactory binding with custom IInstanceProvider but unless we're going to create lots of factories with FileCodeParameters i don't think it makes sense, so let's keep it simple:
public interface IFileProcessorFactory
{
FileProcessor Create(FileCode fileCode);
}
internal class FileProcessorFactory : IFileProcessorFactory
{
private readonly IResolutionRoot resolutionRoot;
public FileProcessorFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public FileProcessor Create(FileCode fileCode)
{
return this.resolutionRoot.Get<FileProcessor>(new FileCodeParameter(fileCode));
}
}
Now let's have it all come together:
public class Test
{
[Fact]
public void FactMethodName()
{
var fooFileCode = new FileCode("foo");
var barFileCode = new FileCode("bar");
var kernel = new StandardKernel();
kernel
.Bind<IFileProcessorFactory>()
.To<FileProcessorFactory>();
kernel
.Bind<IThing>()
.To<ThingFoo>()
.WhenFileCode(fooFileCode);
kernel
.Bind<IThing>()
.To<ThingBar>()
.WhenFileCode(barFileCode);
kernel
.Bind<IOtherThing>()
.To<OtherThingFoo>()
.WhenFileCode(fooFileCode);
kernel
.Bind<IOtherThing>()
.To<OtherThingBar>()
.WhenFileCode(barFileCode);
var fileProcessor = kernel.Get<IFileProcessorFactory>().Create(barFileCode);
fileProcessor.Thing.Should().BeOfType<ThingBar>();
fileProcessor.Thing.FileCode.Should().Be(barFileCode);
fileProcessor.OtherThingWrapper.OtherThing.Should().BeOfType<OtherThingBar>();
fileProcessor.OtherThingWrapper.OtherThing.FileCode.Should().Be(barFileCode);
}
}
public static class BindingExtensionsForFileCodes
{
public static IBindingInNamedWithOrOnSyntax<T> WhenFileCode<T>(
this IBindingWhenSyntax<T> syntax,
FileCode fileCode)
{
return syntax.When(req => req
.Parameters
.OfType<FileCodeParameter>()
.Single()
.FileCode.Value == fileCode.Value);
}
}
That's it!
- the FileCode is both being injected and being used for selection of implementation
- as the parameter is "inherited", it also works deeper down the object tree.
Below, just for reference, all of the code for easier copy & paste:
using FluentAssertions;
using Ninject;
using Ninject.Activation;
using Ninject.Parameters;
using Ninject.Planning.Targets;
using Ninject.Syntax;
using System.Linq;
using Xunit;
namespace NinjectTest.ParameterContextual
{
public class FileCode
{
public FileCode(string value)
{
Value = value;
}
public string Value { get; private set; }
}
public interface IThing
{
FileCode FileCode { get; }
}
public abstract class Thing : IThing
{
protected Thing(FileCode fileCode)
{
FileCode = fileCode;
}
public FileCode FileCode { get; private set; }
}
public class ThingFoo : Thing
{
public ThingFoo(FileCode fileCode) : base(fileCode) { }
}
public class ThingBar : Thing
{
public ThingBar(FileCode fileCode) : base(fileCode) { }
}
public interface IOtherThing
{
FileCode FileCode { get; }
}
public abstract class OtherThing : IOtherThing
{
protected OtherThing(FileCode fileCode)
{
FileCode = fileCode;
}
public FileCode FileCode { get; private set; }
}
public class OtherThingFoo : OtherThing
{
public OtherThingFoo(FileCode fileCode) : base(fileCode) { }
}
public class OtherThingBar : OtherThing
{
public OtherThingBar(FileCode fileCode) : base(fileCode) { }
}
public class OtherThingWrapper
{
public OtherThingWrapper(IOtherThing otherThing)
{
OtherThing = otherThing;
}
public IOtherThing OtherThing { get; private set; }
}
public class FileProcessor
{
public FileProcessor(IThing thing, OtherThingWrapper otherThingWrapper)
{
Thing = thing;
OtherThingWrapper = otherThingWrapper;
}
public IThing Thing { get; private set; }
public OtherThingWrapper OtherThingWrapper { get; private set; }
}
public interface IFileProcessorFactory
{
FileProcessor Create(FileCode fileCode);
}
internal class FileProcessorFactory : IFileProcessorFactory
{
private readonly IResolutionRoot resolutionRoot;
public FileProcessorFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public FileProcessor Create(FileCode fileCode)
{
return this.resolutionRoot.Get<FileProcessor>(new FileCodeParameter(fileCode));
}
}
public class Test
{
[Fact]
public void FactMethodName()
{
var fooFileCode = new FileCode("foo");
var barFileCode = new FileCode("bar");
var kernel = new StandardKernel();
kernel
.Bind<IFileProcessorFactory>()
.To<FileProcessorFactory>();
kernel
.Bind<IThing>()
.To<ThingFoo>()
.WhenFileCode(fooFileCode);
kernel
.Bind<IThing>()
.To<ThingBar>()
.WhenFileCode(barFileCode);
kernel
.Bind<IOtherThing>()
.To<OtherThingFoo>()
.WhenFileCode(fooFileCode);
kernel
.Bind<IOtherThing>()
.To<OtherThingBar>()
.WhenFileCode(barFileCode);
var fileProcessor = kernel.Get<IFileProcessorFactory>().Create(barFileCode);
fileProcessor.Thing.Should().BeOfType<ThingBar>();
fileProcessor.Thing.FileCode.Should().Be(barFileCode);
fileProcessor.OtherThingWrapper.OtherThing.Should().BeOfType<OtherThingBar>();
fileProcessor.OtherThingWrapper.OtherThing.FileCode.Should().Be(barFileCode);
}
}
internal class FileCodeParameter : IConstructorArgument
{
private readonly FileCode fileCode;
public FileCodeParameter(FileCode fileCode)
{
this.fileCode = fileCode;
}
public string Name { get { return "File Code Parameter"; } }
public bool ShouldInherit { get { return true; } }
public FileCode FileCode { get { return this.fileCode; } }
public bool Equals(IParameter other)
{
var otherFileCodeParameter = other as FileCodeParameter;
if (otherFileCodeParameter == null)
{
return false;
}
return otherFileCodeParameter.fileCode == this.fileCode;
}
public object GetValue(IContext context, ITarget target)
{
return this.fileCode;
}
public bool AppliesToTarget(IContext context, ITarget target)
{
return target.Type == typeof(FileCode);
}
}
public static class BindingExtensionsForFileCodes
{
public static IBindingInNamedWithOrOnSyntax<T> WhenFileCode<T>(
this IBindingWhenSyntax<T> syntax,
FileCode fileCode)
{
return syntax.When(req => req
.Parameters
.OfType<FileCodeParameter>()
.Single()
.FileCode.Value == fileCode.Value);
}
}
}

Create factory pattern

I'm trying to use the factory pattern and have created three interfaces.
ITest1
public interface ITest1: ITestX
{
void Write(string name);
}
ITest2
public interface ITest2: ITestX
{
void Read(string name);
}
and ITestX
public interface ITestX
{
}
The interfaces ITest1 and ITest1 are implemented in classes A and B:
public class A: ITest1
{
public void Write(string name)
{
Console.WriteLine(name);
}
}
public class B: ITest2
{
public void Read(string name)
{
Console.WriteLine(name);
}
}
As for the factory, my interface looks like this:
public interface IFactory
{
ITestX GetClass(ClassType cType);
ITestX GetClass(int cType);
}
The class ClassType:
public class ClassT
{
public int Type { get; set; }
public static class ClassType
{
public const int AType = 0;
public const int BType = 1;
}
}
The Factory class which implements the factory interface:
public class Factory : IFactory
{
public ITestX GetClass(ClassType cType)
{
return GetNetwork(networkType.Type);
}
public ITestX GetClass(int cType)
{
switch (cType)
{
case ClassT.ClassType.AType:
return new A();
case ClassT.ClassType.BType:
return new B();
default:
throw new NotImplementedException();
}
}
}
In my test method, I try to use the factory:
Factory factory = new Factory();
var typeClass = factory.GetClass(new ClassT{ Type = ClassT.ClassType.AType });
However, I can't use the Read or Write methods because they are not visible in typeClass. What's going on? Why can't I access them?
Because Factory.GetClass returns ITextX, and this interface doesn't have that methods declared.
You can try casting that objects to the interface you need and then you will have an opportunity to invoke corresponding methods.
UPDATE:
You can see an example implementation on the wiki page.
Example:
public interface ICanRead
{
string Read();
}
public interface ICanWrite
{
void Write(string name);
}
public interface ICanReadAndWrite : ICanRead, ICanWrite {}
class ConsoleReadWriter : ICanReadAndWrite
{
public string Read()
{
return Console.ReadLine();
}
public void Write(string name)
{
Console.WriteLine(name);
}
}
public interface IReadWriterFactory
{
ICanReadAndWrite GetClass();
}
public class ConsoleReadWriterFactory : IReadWriterFactory
{
public ICanReadAndWrite GetClass()
{
return new ConsoleReadWriter();
}
}
Create a class implementing the IReadWriterFactory interface for other Classes of ReadWriters.
I think what you rather need is this:
class Program
{
static void Main(string[] args)
{
ReadWriter myReadWriter = new ReadWriter(new ConsoleReaderWriterFactory());
string test = myReadWriter.Read();
myReadWriter.Write("this is abstract factory power");
}
}
public class ConsoleWriter : ICanWrite
{
public void Write(string name)
{
Console.WriteLine(name);
}
}
public class ConsoleReader : ICanRead
{
public string Read()
{
return Console.ReadLine();
}
}
public interface ICanWrite
{
void Write(string name);
}
public interface ICanReadAndWrite : ICanRead, ICanWrite { }
public interface ICanRead
{
string Read();
}
public class ReadWriter : ICanReadAndWrite
{
private ICanRead reader;
private ICanWrite writer;
public string Read()
{
return reader.Read();
}
public void Write(string name)
{
writer.Write(name);
}
public ReadWriter(IReaderWriterFactory factory)
{
reader = factory.CreateReader();
writer = factory.CreateWriter();
}
}
public interface IReaderWriterFactory
{
ICanRead CreateReader();
ICanWrite CreateWriter();
}
public class ConsoleReaderWriterFactory : IReaderWriterFactory
{
public ICanRead CreateReader()
{
return new ConsoleReader();
}
public ICanWrite CreateWriter()
{
return new ConsoleWriter();
}
}

using generic method in abstract class with child class result

I'm working to DRY some code up and I'm running into the following situation. I've reworked the code to provide a better example of the scenario.
namespace SourceCode
{
public interface IFactory
{
public baseClass GenerateClass();
public bool IsUsable();
}
public abstract baseClass
{
...
}
public AClass:baseClass
{
...
}
public class FactoryA:IFactory
{
public baseClass GenerateClass()
{
return new AClass();
}
public bool IsUsable(){
{
return true if some condition;
}
}
public BClass:baseClass
{
...
}
public class FactoryB:IFactory
{
public baseClass GenerateClass()
{
return new BClass();
}
public bool IsUsable(){
{
return true if some condition;
}
}
public static class FactoryProvider
{
List<IFactory> factories
static FactoryProvider()
{
factories.Add(new FactoryA());
factories.Add(new FactoryB());
}
static List<baseClass> GetClasses()
{
return (from f in factories where f.IsUsable() select f).ToList();
}
}
}
namespace SourceCode.Tests
{
public class baseTests
{
public T GenericMethod<T>(){...}
}
public class ClassATests:baseTests
{
public void Test1()
{
... generic used in a method provided by the base class
}
}
public class ClassBTests:baseTests
{
public void Test1()
{
... generic used in a method provided by the base class
}
}
}
So the problem in my tests is that there are tests that will have to happen for every child class.
UPDATE=======================
I was able to solve my issue by doing the following.
namespace SourceCode.Tests
{
public class baseTests<I> where I: baseClass
{
public void Test1()
{
var result = GenericMethod<I>();
// The generic method will use ClassA for ClassATests
// and ClassB for ClassBTests
}
public T GenericMethod<T>(){...}
}
public class ClassATests:baseTests<ClassA>
{
}
public class ClassBTests:baseTests<ClassB>
{
}
}
Making your current A class generic could solve problems:
abstract class A
{
// protected members...
protected abstract A InternalGetData(List<A> src);
public void SharedMethodHappensAlways()
{
List<A> src = new List<A>();
var childResult = InternalGetData(src);
}
}
abstract class A<T> : A
where T: A
{
public T GetData(List<A> src)
{
return src.OfType<T>().FirstOrDefault();
}
protected override A InternalGetData(List<A> src)
{
return GetData(src);
}
}
class B : A<B>
{
}
class C : A<C>
{
}
Sample usage:
List<A> src = new List<A>() { new B(), new C() };
B b = new B();
b.SharedMethodHappensAlways();
B firstB = b.GetData(src); // returns first instance of B
C firstC = new C().GetData(src);

Categories