I have an abstract class which has generic
public abstract class BaseService<T>
{
public abstract void Read(T param);
}
and I have few other classes which is extending this abstract class
public class ServiceOne : BaseService<DTOParam>
{
public override void Read(DTOParam param)
{
//Do something with this DTOParam
}
}
//Other class
public class ServiceTwo : BaseService<DTOParamtwo>
{
public override void Read(DTOParamtwo param)
{
//Do something with this DTOParamtwo
}
}
I have been trying to Instantiate these class like
BaseService<T> bs = new ServiceOne();
which is throwing and error as
Cannot implicitly convert type ServiceOne to BaseService<T>
If you remove the generic it is working fine, What I am missing here? Or is the above approach not possible at all.
A generic class is a semantic trick, when you instantiate or create a derived from a generic class the compiler creates a different class for each type. Thus, there's no way to cast a derived class which implements a concrete type to a typeless base.
You have two options, cast to the concrete generic type or create an underliying common base (i think the second option is what you really want). To create a common base, in your implementation you would also create on the base a function which accepts an Object as parameter and that function would call to the real generic implementation (see the example below).
Cast to concrete type:
BaseService<DTOParam> bs = new ServiceOne();
Create a common base:
public abstract class BaseService
{
public abstract void Read(object parm);
}
public abstract class GenericBaseService<T> : BaseService
{
public override void Read(object parm)
{
Read((T)parm);
}
public abstract void Read(T parm);
}
public class ServiceOne : GenericBaseService<DTOParam>
{
public override void Read(DTOParam param)
{
//Do something with this DTOParam
}
}
//Now you can do:
BaseService srv = new ServiceOne();
srv.Read(dataOnject);
The case sensitivity might be an issue. If you have two classes declared, Baseservice<T> and BaseService<T> then you could be using the wrong type.
The problem is likely in the method declaration that contains the statement.
For example, this won't work:
public static BaseService<T> GetService<T>()
{
BaseService<T> returnValue = new ServiceOne();
return returnValue;
}
because T could be any type, so you can't assign ServiceOne, which is a BaseService<DTOParam>, to BaseService<T>. What if T is int or some other type? You can't assign BaseService<DTOParam> to BaseService<ItMightBeAnything>.
This, on the other hand, works:
public static BaseService<DTOParam> GetService()
{
BaseService<DTOParam> returnValue = new ServiceOne();
return returnValue;
}
You can not create abject and cast at generic type T:
Baseservice bs = new ServiceOne();
should be:
ServiceOne bs = new ServiceOne();
You can later cast bs to base class if you need, but you need and generic type:
Baseservice bs1 = (BaseService<DTOParam>)bs;
Or if you insist on casting on creating instance should be:
Baseservice<DTOParam> bs = new ServiceOne();
You have a typo in your code BaseService should be Baseservice:
public class ServiceOne : Baseservice<DTOParam>
{
public override void Read(DTOParam param)
{
//Do something with this DTOParam
}
}
Related
I have this generic class:
public abstract class FilterPage<T> where T : IResponse
{
protected List<T> apiResults;
public abstract List<T> Post();
}
And this class that inherites from FilterPage:
public class ExportImportPage : FilterPage<DemandExportReport>
{
public override List<DemandExportReport> Post()
{
return apiResults = API.Post<List<DemandExportReport>>(FilterReqtUrl);
}
}
public class DemandExportReport : IResponse
{
...
}
And here I have the class where I am doing my initializations:
class TestClass
{
public void Method1()
{
FilterPage<DemandExportReport> myInst = new ExportImportPage();
}
public void Method2()
{
// I want to use myInst here.
}
}
In TestClass, if I declare and initialize myInst in Method1() as FilterPage<DemandExportReport> myInst = new ExportImportPage(), it works fine. My problem is that I don't know the type at compile time. Instead of DemandExportReport I may use a different type. I want to initialize myInst in Method1() and then use it in other methods, being able to call myInst.Post(). So, how can I declare myInst without doing FilterPage<DemandExportReport> myInst;, as I want to use several types with FilterPage instead of DemandExportReport?
Note: If I create a non-generic base class, let's say BaseFilterPage, and then inherite FilterPage<t> from it, I am able to declare a BaseFilterPage instance class. The problem is that with that variable I don't have access to the Post() method. And I cannot move the Post() declaration to BaseFilterPage because it is a generic method.
I would like to associate an object of type AbstractObject to my current Class.
However, this has to be done in the constructor, since, when I define my Class I don't know which type of object would be associated (only that this is of type AbstractObject). And I need to construct the associated object in my class (So I can't put an instance as parameter).
So it would be something like:
public abstract class MyClass
{
public MyClass(Type T) where T : AbstractObject
{
(T)Actiocator.CreateInstance(Typeof(T));
//To do
}
}
but this doesn't work. Any idea how to fix this?
Depending on your use case, there are several options.
Passing in the object
The simplest way is have the caller construct the object, and pass it in through the constructor:
public MyClass(AbstractObject template)
{
// Do something with template
}
Provide a static factory method
Expanding on the idea above, if you want to have control over the object that the constructor uses, you can provide a static method that creates a Base object and passes it to the constructor:
private MyClass(AbstractObject template)
{
// Do something with template
}
public MyClass Create<T>() where T : AbstractObject, new()
{
// Create a temporary object just for passing into the private ctor
return new MyClass(new T());
}
I made the constructor private so you can create a new MyClass object only through the static instance:
MyClass.Create<Concrete>();
Also note I added the new() constraint, so I can simply write new T. This is fine if you know that T is going to a be a derived class of AbstractObject which is a reference type. If you want to be able to construct MyClasses from value types such as int, you can drop the new() constraint and use reflection.
Make the class generic
If you also need to store the object in your class, make the whole class generic:
public class MyClass<T> where T : AbstractObject, new()
{
private T myObject;
public MyClass()
{
this.myObject = new T();
// Do other stuff
}
}
Create a interface or a abstract class them implement it in the class you want to pass into the current class constructor
public interface ITest
{
// your interface method and properties
}
public class Child : ITest
{
// do your stuff here
}
public abstract class MyClass
{
public MyClass(ITest tes)
{
// do stuff using test
}
}
maybe something like this would suit you?
abstract class AbstractObject {}
class Test : AbstractObject
{
public Test()
{
Console.WriteLine("I work");
}
}
class GenTest<T> where T: AbstractObject, new()
{
T obj;
public GenTest()
{
obj = new T();
}
}
public static void Main()
{
var genTestObj = new GenTest<Test>();
}
Try this:
public abstract class MyClass<T> where T : AbstractObject, new()
{
public MyClass(T type)
{
T instance = new T();
}
}
If you add new() in the generics constraints, you can call the parameterless constructor of your class.
https://msdn.microsoft.com/en-us/library/bb384067.aspx
Maybe this is a dumb question. But, I don't get the point what I am missing.
Given the following class-definition
public abstract class AbstractBaseClass
{
public abstract void Create(AnotherAbstractClass param1);
}
Wheras AnotherAbstractClass is defined
public abstract class AnotherAbstractClass
{
}
with a concrete implementation
public class AnotherConcreteImplementation : AnotherAbstractClass
{
}
I want to be able to have the override of the Create method to use a concrete type:
public class ConcreteImplementation : AbstractBaseClass
{
public override void Create(AnotherConcreteImplementation param1) <-- There is no suitable method for override
{
// param1 is an instance of the concrete implementation
}
public override void Create(AnotherAbstractClass param1) <-- this is working but I'll have to cast on each implementation
{
// param1 is an instance of the abstract class and needs a cast
}
}
Is this simply not possible or is there some way I'm not aware of? Maybe using generics?
Edit #1 (added more context)
I'm trying to achieve/enforce that in a concrete implementation there is only one parameter valid.
Think of it like it's a database-layer. The Create method will create a new entry in the database. As of each table has different values, the create-parameter also has.
The casting inside smells (in my opinion) as of it can be called with any concrete implementation of AnotherAbstractClass.
public class AddressTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteAddressCreate)param1;
}
}
public class CityTable : AbstractBaseClass
{
public override void Create(AnotherAbstractClass param1)
{
// cast to concrete instance
var casted = (ConcreteCityCreate)param1;
}
}
Having an instance of AddressTable I can call
addressIntance.Create(new ConcreteAddressCreate()); // would be okay
on the other hand I can call it
addressIntance.Create(new ConcreteCityCreate()); // would be okay but will fail at runtime with InvalidCastException
Edit #2 (additional info)
It should also be possible to extend the AbstractBaseClass class with more abstract methods later.
So, for me it's more likely to have generic methods instead of an concrete class-implemenation with 200 generic parameters for each method to implement.
It violates the Liskov Substitution Principle so it makes perfect sense you can't do this. Namely, you can't just "have" covariance like this for free:
AbstractBaseClass bcl = new ConcreteImplementation();
bcl.Create(new DifferentImplementationWithoutSecondAbstract());
The contract AbstractBaseClass defines makes Create have to work with any implementation of AbstractBaseClass passed in - if you give a constraint on what can be passed in you've violated the contract it defines.
Like you assumed - you can use generics:
// notice the recursive definition, we require the generic parameter
// to be a generic parameter of itself - allowing AbstractBaseClass
// to not be aware of its subclasses like in the other answers.
public abstract class AbstractBaseClass<T> where T : AbstractBaseClass<T>
{
public abstract void Create(T param1);
}
public class Concrete : AbstractBaseClass<Concrete>
{
public override void Create(Concrete param1)
{
Console.WriteLine("Hello!");
}
}
Yes, you can do that using generics:
public abstract class AbstractBaseClass<T>
where T : AnotherAbstractClass
{
public abstract void Create(T param1);
}
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1)
{
}
}
Generics is indeed the way to do it.
public abstract class AbstractBaseClass<TDerivedClass> where TDerivedClass : AnotherAbstractClass
{
public abstract void Create(TDerivedClass param1);
}
And then you can do:
public class ConcreteImplementation : AbstractBaseClass<AnotherConcreteImplementation>
{
public override void Create(AnotherConcreteImplementation param1) // Works because TDerivedClass = AnotherConcreteImplementation
{
...
}
}
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 could very will be imagining things, but I seem to recall in Java that I can declare a field or parameter as such:
public class BarHandler{
public Class<? extends Foo> fooType;
public ProcessedBar Process(string xml){
Foo foo = fooType.GetInstance();
return foo.process(xml)
}
}
This can be useful for factory style systems where you have to be able to generate new instances of the type in question for example.
I am trying to figure out if there is an analog to this in C#, or if possibly this is just something that is available within Java.
Yes, see generic constraints. The equivalent to your example would be:
public class SomeClass<T>
where T : Foo
{
private T fooType;
}
EDIT AFTER YOUR EDIT: I believe you're referring to wildcards, in which case you should read about covariance and contravariance with respect to generics.
Here's a variation of 280Z28's answer. I've renamed the "Type" class to "Factory", since in my version it exposes a GetInstance method instead of a Value property of type Type. This uses 2 generic parameters and generic constraints to enforce the rules that were in the original answer's constructor for the Type class.
public abstract class Factory<T>
{
public abstract T GetInstance();
}
public sealed class IoCFactory<T, TDerived> : Factory<T>
where TDerived : T // compiler enforces that TDerived derives from T
{
public override T GetInstance()
{
// TODO: retrieve instance of TDerived from IoC container such as Spring.NET, StructureMap, Unity, etc.
throw new NotImplementedException();
}
}
public sealed class ActivatorFactory<T, TDerived> : Factory<T>
where TDerived : T, new() // compiler enforces that TDerived derives from T and that it has a parameterless constructor
{
public override T GetInstance()
{
return Activator.CreateInstance<TDerived>();
}
}
public class BarHandler
{
public Factory<Foo> fooFactory { get; set; }
public ProcessedBar Process(string xml)
{
Foo foo = fooFactory.GetInstance();
return foo.Process(xml);
}
}
class Program
{
static void Main(string[] args)
{
BarHandler handler = new BarHandler();
handler.fooFactory = new ActivatorFactory<Foo, Bar>();
var processedResult = handler.Process("<bar>Yar!</bar>");
}
}
public class GenericClass<T> where T : Foo
You could use a very simple wrapper for this annotation and a cheap runtime check:
public sealed class Type<T>
{
public Type(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
if (!typeof(T).IsAssignableFrom(type))
throw new ArgumentException(string.Format("The specified type must be assignable to '{0}'.", typeof(T).FullName));
this.Value = type;
}
public Type Value
{
get;
private set;
}
}
Use Activator.CreateInstance to actually create an instance of the type. Suppose FooDerived is derived from Foo.
Type<Foo> fooType = new Type<Foo>(typeof(FooDerived));
Activator.CreateInstance(fooType.Value);