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.
Related
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
}
}
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
There are two files A.cs and B.cs. There is a method fn() which is used in both the classes.
Method fn() is used in both class files. This increases code complexity if I need this method in many class files (say 100 files).
I know that we can call this method by creating an object for the class in which this method is defined. How can I share this function between two or more classes without creating an object every time for accessing this method?
Put the method in a static class:
public static class Utils
{
public static string fn()
{
//code...
}
}
You can then call this in A.cs and B.cs without creating a new instance of a class each time:
A foo = new A();
foo.Property = Utils.fn();
Alternatively, you could create a BaseClass that all classes inherit from:
public class BaseClass
{
public BaseClass() { }
public virtual string fn()
{
return "hello world";
}
}
public class A : BaseClass
{
public A() { }
}
You would then call fn() like so:
A foo = new A();
string x = foo.fn();
I hope the function isn't really called fn(), but actually named to what it does, like CalculateTotal(). Then you can extract this method into a class, say: TotalCalculator.
Now upon application startup, preferably using dependency injection, you create one instance of the class that gets shared between objects that require it. Like so:
class TotalCalculator
{
public int Calculate()
{
return 42;
}
}
class NeedsCalculator1
{
TotalCalculator _calculator;
public NeedsCalculator1(TotalCalculator calculator)
{
_calculator = calculator;
}
public void Foo()
{
_calculator.Calculate();
}
}
class NeedsCalculatorToo
{
TotalCalculator _calculator;
public NeedsCalculatorToo(TotalCalculator calculator)
{
_calculator = calculator;
}
public void Bar()
{
_calculator.Calculate();
}
}
Then you instantiate the calculator once, and pass it into the other classes' constructor:
TotalCalculator calculator = new TotalCalculator();
NeedsCalculator1 dependency1 = new NeedsCalculator1(calculator);
NeedsCalculatorToo dependency2 = new NeedsCalculatorToo(calculator);
You can now further abstract the calculator dependency by creating a base class containing the constructor and a protected TotalCalculator instance field, for example.
Assuming that this method is self contained, you could create a static class and put this method as a static method in it, which is in turn, called by the other classes.
If is is not self contained, you could try and declare it in some super class and let the other 100 classes extend that class.
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 have a baseclass which has public contructors.
The baseclass is not sealed and is not abstract.
There is one constructor which I desire to be sealed. Is this possible?
My current attempt results in syntax error saying the constructor cannot be sealed.
public sealed MyBase(string someParam)
Additional:
I wish to be able to instantiate the base class directly and have access to the sealed constructor. Derived classes cannot use that constructor via the derived constructors.
E.g.
public MyDerived() : base(string cant_access_my_sealed_constructor)
You can't do that. If the constructor is public, you can call it from constructors of derived classes. But you can do something close – you can have a private constructor and a public static method that calls it:
class MyBase
{
private MyBase(string someParam)
{
// some code
}
public static MyBase Create(string someParam)
{
return new MyBase(someParam);
}
protected MyBase() // or some other protected or public constructor
{ }
}
class MyDerived : MyBase
{
public MyDerived()
: base("foo") // won't compile, as requested
{ }
}
All constructors are "sealed" in that they cannot be "overridden." They can only be called from the constructor in a child class.
If you are hoping to prevent child classes from having a constructor with the same signature, that cannot be done.
Based on the additional information you added to the post, it sounds like what you want to do is make your constructor private, as Kyle suggested. This will prevent the child class from calling the constructor, but it won't prevent it from taking the same types of arguments:
public class Foo
{
private Foo(string s){
}
// Allowed
public Foo() : this("hello") {
}
}
public class Bar : Foo
{
// Allowed
public Bar(string s) : base(){
}
// Not allowed
public Bar(string s) : base(s){
}
}
If you want to prevent the constructor from being called by inherited classes, just mark it private.
Constructors aren't inherited by a child class, you have to explicitly call a base constructor if desired.
This code will call the base class' no-parameter constuctor when an instance of the child class is instantiated. Without it, the base class' constructor won't be called when creating a new instance of the child class.
public class A
{
public A()
{
}
}
public class B : A
{
public B()
: base()
{
}
}