This is the kind of thing I want to do:
Interface IMyInterface
{
List<IMyInterface> GetAll(string whatever)
}
so that classes implementing this must have a function that returns a list of their own type.
Is this even possible?
I know that - technically - a class implementing this could return a list of other classes which implement this, not necessarily the same class, but I can live with that even though it isn't ideal.
I have tried this, but I can't get the implementing class to correctly implement the method.
Implementing this interface is straight forward:
public class MyInterfaceImpl : IMyInterface
{
public List<IMyInterface> GetAll(string whatever)
{
return new List<IMyInterface> { new MyInterfaceImpl(), this };
}
}
Please note that the method signature needs to be exactly the same, i.e. the return type has to be List<IMyInterface> and not List<MyInterfaceImpl>.
If you want the type in the list to be the same type as the class that implements the interface, you will have to use generics:
public interface IMyInterface<T> where T : IMyInterface<T>
{
List<T> GetAll(string whatever)
}
public class MyInterfaceImpl : IMyInterface<MyInterfaceImpl>
{
public List<MyInterfaceImpl> GetAll(string whatever)
{
return new List<MyInterfaceImpl > { new MyInterfaceImpl(), this };
}
}
This is a normal solution. Consider you have interface IPerson and you want to access each parent of a person. So it would be reasonable to have interface declaration as following:
interface IPerson
{
IList<IPerson> GetAllParents();
}
Now you are able to get parents of that parents and then get parents... Hope you got the idea. Such design is very flexible, because it allows to model deep dynamic structures using simple static models.
Implementation is very straight-forward:
class Person : IPerson
{
IList<IPerson> parents;
public Person(IList<IPerson> parents)
{
this.parents = parents;
}
public IList<IPerson> GetAllParents()
{
return parents;
}
}
In some sense you need to create some Persons without parents (some kind of Adam and Eve) and then add childs by holding references to their parents. As you can see, my naive model can handle randomly deep family structures, while having very simple interface exposed outside.
This works for me:
public interface IMyInterface
{
List<IMyInterface> GetAll(string whatever);
}
public class Program : IMyInterface
{
public string Member { get; set; }
public List<IMyInterface> GetAll(string whatever)
{
return new List<IMyInterface>()
{ new Program() { Member = whatever } };
}
static void Main(string[] args)
{
List<IMyInterface> all = new Program().GetAll("whatever");
Console.WriteLine(all.Count);
}
}
I don't see why interface could not reference itself - no problem with below.
interface ITest
{
List<ITest> GetAll(string whatever);
}
class MyClass : ITest
{
public List<ITest> GetAll(string whatever)
{
return new List<ITest>();
}
}
Related
lately I started to learn generics. I run into trouble with storing references to generic classes instances. As you can see, my class ListHandler can store references to specific type of BaseClass. I would love to register BaseClass instances by themselves, which is why I wanted to guarantee that they will use BaseParamClass by adding 'where'. Anyway - it does not compile.'This', does not know that T is actually BaseClassParam even with 'where' keyword in class. I don't know what is wrong here and I couldn't find answer anywhere. I would be grateful for tips/guides/solutions.
public class ListHandler
{
private List<BaseClass<BaseParamClass>> list;
public ListHandler()
{
list = new List<BaseClass<BaseParamClass>>();
}
public void Register(BaseClass<BaseParamClass> param)
{
list.Add(param);
}
}
public class BaseClass<T> where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this); //throws error
}
}
Why don't you make ListHandler generic as well?
public class ListHandler<T>
{
private List<BaseClass<T>> list;
public ListHandler()
{
list = new List<BaseClass<T>>();
}
public void Register(BaseClass<T> param)
{
list.Add(param);
}
}
public class BaseClass<T>
{
private ListHandler<T> listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler<T> listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Also, it seems strange to me to have BaseClass<T> contain a reference to a class that has a reference to BaseClass<T> itself.
I have another option for you.
Let's split the BaseClass<T> class into two with a non-generic base, like so:
public class BaseClass
{
protected ListHandler listHandler;
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
}
}
public class BaseClass<T> : BaseClass where T : BaseParamClass
{
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
: base(listHandler)
{
listHandler.Register(this); // Compiles nicely! Yay!
}
}
Now, the list inside ListHandler can be defined as private List<BaseClass> list;. That means there is no problem adding any BaseClass item to the list. We also can then define two methods for registering and fetching generic versions of the BaseClass<T> from the ListHandler. It would look like this:
public class ListHandler
{
private List<BaseClass> list;
public ListHandler()
{
list = new List<BaseClass>();
}
public void Register<T>(BaseClass<T> param) where T : BaseParamClass
{
list.Add(param);
}
public BaseClass<T> Fetch<T>() where T : BaseParamClass
{
return list.Select(x => x as BaseClass<T>).Where(x => x != null).FirstOrDefault();
}
}
So, given a class public class FooParam : BaseParamClass { } I can write this code:
ListHandler listHandler = new ListHandler();
BaseClass<FooParam> baseClass = new BaseClass<FooParam>(listHandler);
BaseClass<FooParam> baseClass2 = listHandler.Fetch<FooParam>();
Console.WriteLine(object.ReferenceEquals(baseClass, baseClass2));
The result from this code is True is written to the console - which means I can successfully fetch the instance of BaseClass<FooParam> from the ListHandler.
Why your code doesn't compile
In order to fully understand why your code doesn't compile, you'll have to dive into covariance and contravariance, which is a big topic and hard to explain in an SO answer. It can be especially confusing if you've gotten to a point where inheritance polymorphism is second nature to you; the rules are just different enough to be make your head hurt.
Here is what is confusing--
You're used to doing this:
object a = new String(...);
But generics don't let you do this!
List<object> c = new List<string>(); //Compiler error
That's because those two Lists are not related the same way that object and string are related. One does not inherit from the other. Rather, they are different variants of a generic type definition. In the generic world, you can't assign one to the other. The same is true of this:
void Foo<T>() where T: BaseParamClass
{
BaseClass<BaseParamClass> a = new BaseClass<T>(); //Compiler error
}
In this example, T could be BaseParamClass or one of its derived types. They are not the same type. So to remain type-safe, the compiler has to disallow this assignment, and your Register call, which has the same type mismatch.
Standard ways around this
You need a covariant interface. These allow assignment from derived to base. So for example, while this is still illegal:
List<object> a = new List<string>(); //Compiler error
This is totally fine:
IEnumerable<object> e = new List<string>(); //Is OK
Because IEnumerable was declared to be covariant, like this:
interface IEnumerable<out T>
Which means it is can be assigned in this way. It works because using out also adds a compiler constraint to the interface: it can be used to retrieve stuff...
interface IEnumerable<out T>
{
T Item[int index];
}
...but it cannot accept anything:
interface IEnumerable<out T>
{
Add(T item); //Compiler error
}
These constraints are what allow generics to provide early-bound type safety while still allowing certain forms of (non-inheritance) polymorphism.
What I'd suggest
Based on your comment, it sounds like you just need a container (a stack, apparently) that can hold references to these BaseClass<T> instances. If you are following separation of concerns, the stack doesn't need to actually do anything with the T, other than store it and retrieve it, and to allow it to register itself.
Since that is a separate concern, make a separate interface.
And in the interest of keeping things simple, maybe avoid using generics completely for this bit.
One way to do it--
Create an interface that allows access to everything the stack needs to know about an item it is containing. For example, if the stack contains popups of various kinds, you may want to expose the popup's title.
interface IStackable
{
string Title { get; set; }
}
Now use it like this:
public class ListHandler
{
private readonly Dictionary<string, IStackable> list;
public ListHandler()
{
list = new Dictionary<string, IStackable>();
}
public void Register(IStackable item)
{
list.Add(item.Title, item);
}
}
public class BaseClass<T> : IStackable where T : BaseParamClass
{
private ListHandler listHandler;
public T Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
public string Title { get; set; }
}
Unless there is some other requirement, you shouldn't need to make it any more complicated than that.
All you really need to do is add an interface. This works:
public class BaseParamClass
{
}
public class ListHandler
{
private List<IBase<BaseParamClass>> list;
public ListHandler()
{
list = new List<IBase<BaseParamClass>>();
}
public void Register(IBase<BaseParamClass> param)
{
list.Add(param);
}
}
public interface IBase<T> where T : BaseParamClass
{
T Param {get; }
}
public class BaseClass : IBase<BaseParamClass>
{
private ListHandler listHandler;
public BaseParamClass Param { get; private set; }
public BaseClass(ListHandler listHandler)
{
this.listHandler = listHandler;
listHandler.Register(this);
}
}
Working code on DotNetFiddle
I've a Generic type, which is used to give some meta data on an object to persist:
public class PersistedElementDefinition<T> where T: IPersistedObject{
List<PersistedPropertyDefinition<T>> PropertiesToPersist {get;set;}
}
public class PersistedPropertyDefinition<T> where T: IPersistedObject{
public Func<T, object> PropertyGetter{get;set;}
public Action<T, object> PropertySetter {get;set;}
}
and I've my IPersistedObject which can give his definition
public interface IPersistedObject{
PersistedElementDefinition<TypeOfTheImplementingType> Definition {get;}
}
The idea is that if I implement IPersistedObject I should implement it like this:
public class MyPersistedObject:IPersistedObject{
PersistedElementDefinition<MyPersistedObject> Definition{get;}
}
When I persist my class have the following thing:
I can't do the following:
public interface IPersistedObject<T>{
PersistedElementDefinition<T> Definition {get;}
}
because:
It would allow to have a MyPersistedObject<SomeOtherObject
At some point I receive an object, and I should be able to see if it implements the IPersistedObject and do some custom action with it.
For the 2, here is an example of what kind of issue I'm facing if I've a Generic interface:
public void Persist<T>(T objectToPersist)where T:IPersistedObject{
...
foreach(PersistedPropertyDefinition<T> property in objectToPersist.PropertiesToPersist){
object objectToSerialize = property.ObjectGetter(objectToPersist);
if(objectToSerialize is IPersistedObject<___Don't know how to put something generic here___>){
Persist((IPersistedObject<___Don't know how to put something generic here___>)objectToSerialize);
}
}
...
}
Is there a possibility in c# to declare an interface with a generic property of the implementing type?
You can use the curiously recurring template pattern to lock this down a bit further. It isn't bulletproof, but assuming you're not a masochist, and you don't mind the fact that it is theoretically possible to create nonsensical implementations of the interface that violate the invariants you are trying to guarantee, you can do this:
public interface IPersistedObject<T> where T : IPersistedObject<T>
{
PersistedElementDefinition<T> Definition {get;}
}
public class PersistedElementDefinition<T> where T: IPersistedObject<T>
{
...
}
public class MyPersistedObject : IPersistedObject<MyPersistedObject>
{
// Here, you are forced to implement a PersistedElementDefinition<MyPersistedObject>,
// which presumably is the reason behind this whole song and dance
PersistedDefinition<MyPersistedObject> Definition { get; }
}
The problem with this, as you noticed at the outset, is that you could simply define public class MyPersistedObject : IPersistedObject<MyOtherPersistedObject>, and end up breaking the contract you are trying to cobble together, which in plain words is the following:
A persisted object must have a gettable definition that is a persisted element definition of its own type
The C# type system is simply not equipped to handle this elegantly. My advice is to get out early, change to object or dynamic where possible and learn to live with the loss of certain compile time guarantees.
Assuming you're willing to sacrifice some compile time safety, you could do things like so:
class Program
{
static void Main(string[] args)
{
var mpo = new MyPersistedObject();
var ptp = mpo.Definition.PropertiesToPersist;
}
}
public class PersistedElementDefinition<T> where T : IPersistedObject
{
private readonly List<PersistedPropertyDefinition<T>> _propsToPersist = new List<PersistedPropertyDefinition<T>>();
public List<PersistedPropertyDefinition<T>> PropertiesToPersist
{
get { return _propsToPersist; }
}
}
public class PersistedPropertyDefinition<T> where T : IPersistedObject
{
public Func<T, object> PropertyGetter { get; set; }
public Action<T, object> PropertySetter { get; set; }
}
public interface IPersistedObject
{
dynamic Definition { get; }
}
public class MyPersistedObject : IPersistedObject
{
private readonly PersistedElementDefinition<MyPersistedObject> _definition = new PersistedElementDefinition<MyPersistedObject>();
public dynamic Definition { get { return _definition; } }
}
This will be generics 101 for many but below is sample code so I can understand better.
public interface IRecordedItemsProcessor<T>
{
ObservableCollection<RecordedItem> Load(string name);
void Save();
RecordedItem Parse(T itemToParse);
}
public class FileLoadingProcessor : IRecordedItemsProcessor<string>
{
public ObservableCollection<RecordedItem> Load(string name)
{
}
public void Save()
{
}
public RecordedItem Parse(string itemToParse)
{
}
}
public class MyClass
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
The issue is that MyClass needs a dependency on IRecordedItemsProcessor<T> but will not compile as it does not know what T is. How can this be resolved? Making MyClass implement a seems odd as all it needs to do is call Load/Save
Thanks
First solution is the most simple one: lift generic declaration to class level, like
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
Then you could instantiate MyClass as following:
var myClass = new MyClass<string>(new FileLoadingProcessor());
Console.WriteLine (myClass);
Second solution is a removing generic input from constructor and inferring types. Then you don't need to specify generic exactly from call. Class declaration will look like:
public class MyClass
{
public void Process<T>(IRecordedItemsProcessor<T> processor)
{
}
}
And then you can call simply
var my = new MyClass();
my.Process(new FileLoadingProcessor());
The Idea is that you always need to specify class-level generics explicitly, but method level generics can be inferred by the compiler.
Third solutions is to encapsulate creation mechanisms inside MyClassFactory. This is quite flexible, but it might seem a little bit complicated, because descendants of IRecordedItemsProcessor<T> don't define generic at class level, so we should go to implemented interfaces and grab there generic types. And only then we can construct Generic MyClass. Listing is given below:
public class MyClassFactory
{
public MyClass<T> MakeMyClassFor<T>(IRecordedItemsProcessor<T> processor)
{
var processorGenericType = processor.GetType()
.GetInterfaces()
.Single(intr=>intr.Name == "IRecordedItemsProcessor`1")
.GetGenericArguments()[0];
var myClassType = typeof(MyClass<>).MakeGenericType(processorGenericType);
return Activator.CreateInstance(myClassType, processor) as MyClass<T>;
}
}
Now you can create MyClass very simply
var myClassFactory = new MyClassFactory();
var res = myClassFactory.MakeMyClassFor(new FileLoadingProcessor());
Console.WriteLine (res);
All of these three approaches have their pros and cons. Consider taking into account the context, in which you are going to use them.
You could do the following:
Create a new interface IRecordedItemsProcessor (non-generic)
Move Load and Save to this IRecordedItemsProcessor
Make IRecordedItemsProcessor<T> inherit from this IRecordedItemsProcessor
Make MyClass expect IRecordedItemsProcessor in its constructor
This makes it clear that MyClass doesn't care what type the processor might be able to parse, or even that it can parse things at all - it only knows that it can save and load.
You could inherit from a non-generic marker interface, this removes the need to know about T in your class:
public interface IRecordedItemsProcessor
{
}
public interface IRecordedItemsProcessor<T> : IRecordedItemsProcessor
{
ObservableCollection<RecordedItem> Load(string name);
void Save();
RecordedItem Parse(T itemToParse);
}
And then you can use any IRecordedItemsProcessor like:
public class MyClass
{
public MyClass(IRecordedItemsProcessor processor)
{
}
}
The generic type, as written, is being declared on the MyClass constructor which means the generic type must be defined at the MyClass level:
public class MyClass<T>
{
public MyClass(IRecordedItemsProcessor<T> processor)
{
}
}
However, if the generic type was declared at a method level, it would only have to be defined at the method level:
public class MyClass
{
public void MyMethod<T>( IRecordedItemsProcessor<T> processor )
{
}
}
EDIT
Based on your comment:
I want a class that can call the Load/Save methods but not be worried
that T is.
Then you'll need 2 interfaces: 1 for the load/save and then one with the parsing. In this case, you could use inheritance:
public interface IRecordedItems
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
}
public interface IRecordedItemsProcessor<T> : IRecordedItems
{
RecordedItem Parse( T itemToParse );
}
public class MyClass : IRecordedItems
{
#region Implementation of IRecordedItems
public ObservableCollection<RecordedItem> Load( string name )
{
throw new NotImplementedException();
}
public void Save()
{
throw new NotImplementedException();
}
#endregion
}
EDIT 2
Based on your gist example, the type dependency could be moved off of the interface and directly into the interface method:
public class RecordedItem {}
public interface IRecordedItemsProcessor
{
ObservableCollection<RecordedItem> Load( string name );
void Save();
RecordedItem Parse<T>( T itemToParse );
}
public class MyClass
{
private readonly IRecordedItemsProcessor _processor;
public MyClass( IRecordedItemsProcessor processor )
{
_processor = processor;
processor.Parse<string>( "foo" );
processor.Parse<int>( 10 );
processor.Parse<RecordedItem>( new RecordedItem() );
}
}
I know I'm not doing this right, but I also know there is a way to do this. I'm trying to be as generic and abstract as possible, otherwise my code is going to get real messy. So I'm using strategy pattern here as well, which is the GetAggregateClient() method.
I want to have an abstract class called AbstractAggregate<T>, so that it uses generics. The generic type will be a series of data classes (BlogItem, ResourceItem, and AskItem), which all inherit from ListItem.
So that's the background info.
The problem here is that I want GetAbstractAggregate() to return an instance of one of the client classes that implements AbstractAggregate, with the type of item specified depending on the enum passed in. However, I cannot return an AbstractAggregate<T>. The compiler won't let me, and that makes sense since, since the AbstractAggregateFactory class is not a generic.
Does anyone know the best way to do this?
Thanks a lot.
public static class AggregateHelper
{
public enum AggregateTypes { TankTruckBlog, AskTankTruck, Resources }
}
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient(AggregateHelper.AggregateTypes type)
{
switch (type)
{
case AggregateHelper.AggregateTypes.AskTankTruck:
return new AskTankTruckAggregate<AskItem>();
case AggregateHelper.AggregateTypes.TankTruckBlog:
return new TankTruckBlogAggregate<BlogItem>();
case AggregateHelper.AggregateTypes.Resources:
return new ResourcesAggregate<ResourceItem>();
default:
throw new AggregateDoesNotExistException();
}
}
}
public abstract class AbstractAggregate<T>
{
public abstract List<T> GetAggregate(Guid[] resourcetypes);
public abstract T GetSingle(string friendlyname);
}
public class AskTankTruckAggregate<T> : AbstractAggregate<T>
{
// not implemented yet
}
public class TankTruckBlogAggregate<T> : AbstractAggregate<T>
{
// not implemented yet
}
public class ResourcesAggregate<T> : AbstractAggregate<T>
{
// not implemented yet
}
The problem the compiler complains about is that you have a method which is 'open' (T) - and you're returning closed generic (with <AskItem> etc.), concrete type really.
i.e. you have to return a <T> - and you can do that with the method - no matter if the factory is not generic, the method still can be.
As for what's the best way to do it, that's more of a design question, and a bit longer story. I'm not entirely sure what you're trying to achieve (maybe some background story, how many types you might have etc.)
First, your items shouldn't (generally speaking, as a best practice or some 'feels good' factor) inherit from ListItem. Use some other base class of yours, and if you need a collection, use a generic one like List<T>, or create your own IList implementation, etc.
Second, you don't need to make everything generic. Your base aggregator is generic but custom classes are not, usually. For example:
abstract class ItemBase { }
class AskItem : ItemBase { }
class BlogItem : ItemBase { }
class ProvderA : ProviderBase<AskItem>
{
public override AskItem Get()
{
throw new NotImplementedException();
}
}
class ProvderB : ProviderBase<BlogItem>
{
public override BlogItem Get()
{
throw new NotImplementedException();
}
}
abstract class ProviderBase<T> where T : ItemBase
{
public abstract T Get();
}
class Program
{
static void Main(string[] args)
{
ProviderBase<AskItem> provider = GetProvider<AskItem>();
var item = provider.Get();
}
static ProviderBase<T> GetProvider<T>() where T : ItemBase
{
if (typeof(T) == typeof(AskItem))
return (ProviderBase<T>)(object)new ProvderA();
if (typeof(T) == typeof(BlogItem))
return (ProviderBase<T>)(object)new ProvderB();
return null;
}
}
...that's one implementation.
Basically, making everything 'generic' is not always the best way. You have to have enough reasons or 'types' unknown to be possibly used. As with generic you also pay a certain price. Crossing generics to non-generics world is often tricky, and involves reflection if your types can't be inferred by the usage etc.
In my opinion, it's a mistake making each provider generic (<T>), as it only accepts one type (each concrete), while base is generic. So like the above. Usually generic is also constrained per interface where/where you can.
But then you have a problem, as casting back to generic context from effectively a non-generic class is not straight (also have in mind there are caveats with value types as you often have to treat that differently), and vice versa as well.
Hence you need something like cast (object) first.
I'd rather use sort of an IOC approach here - e.g. look at the autofac (I'm not associated but I like how it works, nice framework). In that case you'd do something like this:
container.Register<ProviderBase<AskItem>>(c=> new ProvderA());
container.Register<ProviderBase<BlogItem>>(c => new ProvderB());
// and query later...
ProviderBase<AskItem> provider = container.Resolve<ProviderBase<AskItem>>();
Hope this helps some.
I'm not sure I understand what you are trying to achieve but perhaps it's something like this
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>()
{
if(T is AskItem) return new AskTankTruckAggregate();
if(T is BlogItem) return new TankTruckBlogAggregate();
if(T is ResourceItem) return new ResourcesAggregate();
}
}
public abstract class AbstractAggregate<T>
{
public abstract List<T> GetAggregate(Guid[] resourcetypes);
public abstract T GetSingle(string friendlyname);
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
I'm trying to be as generic and abstract as possible, otherwise my code is going to get real messy.
this is a misconception. being generic/abstract can actually complicate an otherwise simple problem. The key to clean code is encapsulation. much different that inheritance or generics.
In this case I think composition would be a better choice, rather than inheritance. with a set of adaptors you could have a common object that each entity could be adpated to. for example:
interface ICommon { ... }
class AskAdaptor: ICommon
{
private readonly Ask ask;
publick AskAdaptor(Ask ask)
{
this.ask = ask;
}
}
class AskAdaptor: ICommon
{
private readonly Blog blog;
publick AskAdaptor(Blog blog)
{
this.blog = blog;
}
}
class AskAdaptor: ICommon
{
private readonly Resource resource;
publick AskAdaptor(Resource resource)
{
this.resource = resource;
}
}
class CommonAggregate
{
public void Add(ICommon common)
{
....
}
}
How about this:
public static class AggregateHelper
{
public enum AggregateTypes { TankTruckBlog, AskTankTruck, Resources }
}
public class AskItem { }
public class BlogItem { }
public class ResourceItem { }
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>
(AggregateHelper.AggregateTypes type)
{
switch (type)
{
case AggregateHelper.AggregateTypes.AskTankTruck:
return new AskTankTruckAggregate<T>();
case AggregateHelper.AggregateTypes.TankTruckBlog:
return new TankTruckBlogAggregate<T>();
case AggregateHelper.AggregateTypes.Resources:
return new ResourcesAggregate<T>();
default:
throw new ArgumentException();
}
}
}
public abstract class AbstractAggregate<T>
{
public abstract List<T> GetAggregate(Guid[] resourcetypes);
public abstract T GetSingle(string friendlyname);
}
public class AskTankTruckAggregate<T> : AbstractAggregate<T>
{
public override List<T> GetAggregate(Guid[] resourcetypes)
{
throw new NotImplementedException();
}
public override T GetSingle(string friendlyname)
{
Console.WriteLine(friendlyname);
Type whats_t = typeof(T);
return default(T);
}
}
public class TankTruckBlogAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
public class ResourcesAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
Example:
AbstractAggregate<BlogItem> foo3 =
AbstractAggregateFactory.GetAggregateClient<BlogItem>(AggregateHelper.AggregateTypes.AskTankTruck);
foo3.GetSingle("test");
One thing that is possibly clear is that your design is somewhat flawed. A switch on type is not the best thing to do in a generic method which defeats it's purpose. But what is not clear is what the purpose of your classes are.
Some speculations:
1) Seeing your pair classes AskItem and AskTankTruckAggregate<T> etc I dont think the latter has to be a generic class, it is a very specific class, tightly coupled to AskItem. I would redesign it like
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem
{
//use reflection to find the type that inherits AbstractAggregate<T>
//instantiate the type
//cast to AbstractAggregate<T> and return
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Call it like:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
2) Another way: delegate the aggregate creation job to your ListItems.
public abstract class ListItem //or interface
{
protected abstract object Create();
}
public class AskItem : ListItem { //implement to return AskTankTruckAggregate
}
public class BlogItem : ListItem { //implement to return TankTruckBlogAggregate
}
public class ResourceItem : ListItem { //implement to return ResourcesAggregate
}
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem, new()
{
return (AbstractAggregate<T>)new T().Create();
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Call it like:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
3) Or the same, but make it a bit more strongly typed, with the use of generics:
public abstract class ListItem<T> where T : ListItem<T> //or interface
{
protected abstract AbstractAggregate<T> Create();
}
public class AskItem : ListItem<AskItem> { //implement to return AskTankTruckAggregate
}
public class BlogItem : ListItem<BlogItem> { //implement to return TankTruckBlogAggregate
}
public class ResourceItem : ListItem<ResourceItem> { //implement to return ResourcesAggregate
}
public static class AbstractAggregateFactory
{
public static AbstractAggregate<T> GetAggregateClient<T>() where T : ListItem, new()
{
return new T().Create();
}
}
public class AskTankTruckAggregate : AbstractAggregate<AskItem>
{
//not implemented yet
}
public class TankTruckBlogAggregate : AbstractAggregate<BlogItem>
{
//not implemented yet
}
public class ResourcesAggregate : AbstractAggregate<ResourceItem>
{
//not implemented yet
}
Call it like:
AbstractAggregateFactory.GetAggregateClient<AskItem>(); //etc
4) Lastly, may be make the return type less generic? Involves switch case, I dont like it.
public enum AggregateTypes { TankTruckBlog, AskTankTruck, Resources }
public static class AbstractAggregateFactory
{
public static AbstractAggregate GetAggregateClient(AggregateTypes type)
{
switch (type)
{
case AggregateTypes.AskTankTruck:
return new AskTankTruckAggregate<AskItem>();
case AggregateTypes.TankTruckBlog:
return new TankTruckBlogAggregate<BlogItem>();
case AggregateTypes.Resources:
return new ResourcesAggregate<ResourceItem>();
default:
throw new AggregateDoesNotExistException();
}
}
}
public abstract class AbstractAggregate
{
}
public abstract class AbstractAggregate<T> : AbstractAggregate
{
}
//or change the definition to AskTankTruckAggregate : AbstractAggregate<AskItem>
public class AskTankTruckAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
//or change the definition to TankTruckBlogAggregate : AbstractAggregate<BlogItem>
public class TankTruckBlogAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
//or change the definition to ResourcesAggregate : AbstractAggregate<ResourceItem>
public class ResourcesAggregate<T> : AbstractAggregate<T>
{
//not implemented yet
}
Call it like:
AbstractAggregateFactory.GetAggregateClient(AggregateTypes.AskTankTruck); //etc
Imo, this approach is worse than the reflection approach. Its easy to forget some enum checking in future.
Of all, 3rd looks the best to my eyes, but again without knowing your design goal, its very difficult to predict. Few suggestions:
Your factory name sounds better like AggregateFactory. "Abstract" in it makes it more about implementation.
In case you need an enum to denote type, do not make it nested. Nested public types are harder to call. Take out the wrapping static class (as in my 5th approach).
Rename your base class as Aggregate<T> or AggregateBase<T>. Again "Abstract" in it makes it more about implementation, quite needless.
I have a base class that takes a single generic argument. I then have several classes that inherit from this base class. Is there a simple way for the child classes to inherent a factory from the base class?
Example
class BaseClass<T>
{
T Value {get; set;}
string Name {get; set;}
public static BaseClass<T> Factory(T Value)
{
return new BaseClass<T>(Value);
}
}
class ChildClass : BaseClass<int>
{
public void Test()
{
// I want this below to work
// but Factory() returns a BaseClass
ChildClass bs = ChildClass.Factory(10);
}
}
I've noted in the code what I want to work. I can think of one way to overcome this, by adding an implicit operator to either BaseClass or SubClass that converts from BaseClass to ChildClass.
I can also just explicitly add the Factory to ChildClass but that defeats the point of inheritance.
Is there a better, more standardized way of doing this?
I would do something like this:
class BaseClass<T, K> where K : BaseClass<T, K>, new()
{
T Value { get; set; }
string Name { get; set; }
public static K Factory(T value)
{
return new K { Value = value };
}
}
class ChildClass : BaseClass<int, ChildClass>
{
public void Test()
{
ChildClass cs = Factory(10);
}
}
It's a bit hard to answer your question since you have described what you are trying to do, but not why. Hence I got to try to guess what you want.
I would not put the factory method in the same class as in the other answer or your question. How would you handle inheritance for once? It works for the two levels that you have. But what if you want to extend ChildClass?
Instead I would create a generic factory used for the object creation. Implement it has a singleton wrapped around a factory interface to be able to easy extend it or swap the implementation.
class MyFactory
{
private static IMyFactory _instance;
public static void Assign(IMyFactory factory) { _instance = factory; }
public static T Create<T>() { return _instance.Create<T>(); }
}
interface IMyFactory
{
T Create<T>();
}
class MyFactoryImp : IMyFactory
{
//do whatever needed in here
public T Create<T>(){ return new T(); }
}
class BaseClass<T>
{
T Value {get; set;}
string Name {get; set;}
}
class ChildClass : BaseClass<int>
{
public void Test()
{
ChildClass bs = MyFactory.Create<ChildClass>(10);
}
}
// start with this, you can easily switch implementation
MyFactory.Assign(new MyFactoryImp());
The other obvious answer would be to start using a Inversion Of Control container, for example autofac.