Ceate dynamic generic type in c# - c#

I have made a generic class like below:
public abstract class ListCoreDTO<T=int, P=int, G=int, S=int>
{
public T Value { get; set; }
public string Text { get; set; }
public P ParentID { get; set; }
public G Group { get; set; }
public string DetailsInfo { get; set; }
public S SerialNo { get; set; }
}
Here I want calling my generic class like below:
public class ListGenericDTO : ListCoreDTO<T:int, S:long>
{
}
How can I make this type of generic class and my calling class?

As I understand the question, you want to create another generic type which uses some arguments fix and some variable.
When I'm correct, your class signature should look like this
public class ListGenericDTO<P, G> : ListCoreDTO<int, P, G, long>
So the ListCoreDTO-type gets typed with intfor T and long for S.

There is no such thing as an optional generic argument. This is a limitation of the language an something you simply need to workaround.
One way to do such a workaround is to implement inherited classes which fix the generic argument one way or another (see answer from Patrik Eckebrecht). This will allow you to call the generic class as if it had optional arguments, although it will behave with the semantics of a derived class when it comes to using the types.

Related

Overriding abstract list<a> property with list<A>

I'm writing a piece of code to make certain reports. There are 4 types of reports which the user can request. Each type report is based on the base class 'report'. Each derived class has a List. The class 'A' is derived from base class 'a'.
Is it possible to add an abstract List to the 'report' class and let it be overridden by a List in the derived report classes? Something like this?
public abstract class Report
{
public abstract List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
public override List<A> Coils { get; set; }
}
public class a
{
public string SomeProperty { get; set; }
}
public class A: a
{
public string SomeOtherProperty { get; set; }
}
I'm kind of new to C# so if I'm asking something really basic or I have a big flaw in my thinking, please do point it out. But please don't just answer with yes or no.
Based on your description of the usage, there is no need to override the List/collection in your new class. Since A inherits from a, you can store objects of type A in "Coils". (due to polymorphism). Then if, at some later time, you want to access "SomeOtherProperty" of the objects of type A, you could use a cast.
public abstract class Report
{
public List<a> Coils { get; set; }
}
public class ProductionExitCoilReport : Report
{
}
public class a
{
public string SomeProperty { get; set; }
}
public class A : a
{
public string SomeOtherProperty { get; set; }
}
public void SomeMethod()
{
//to store the coil
ProductionExitCoilReport myReport = new ProductionExitCoilReport();
myReport.Coils.Add(new A());
//to retreive SomeOtherProperty from the first element in the list
string retrievedProperty = ((A)myReport.Coils[0]).SomeOtherProperty;
}
Your properties are readable and writable.
Derived types must always be compatible with the base type.
Every Report has Coils property that returns a read/write collections of items of type a. Thus you can always write report.Coils.Add(new a()).
ProductionExitCoilReport inherits from Report, so it would have been possible to run the same code - to add a (not A) to the collection returned by Coils: ((Report)productionReport).Coils.Add(new a()).
This contradicts what you want to accomplish.
Please read about covariance and contravariance:

Get generic field value from list of generic types

I have a bunch of settings that can be one of many types. For example, URL, text, number, etc. Based on other posts I came up with the following that seems to work okay:
public abstract class SettingViewModel
{
public string Name { get; set; }
public string Description { get; set; }
public SettingType Type { get; set; }
public string DefaultValue { get; set; }
public Module? Module { get; set; }
}
public class SettingViewModel<T> : SettingViewModel
{
[Required]
public T Value { get; set; }
}
My biggest problem with this is that when it comes time to read the values in Value for each setting I want to do have a method like. I wouldn't want to change the shape of this method really, because I want to keep it generic and it will be exposed as a Controller Method in MVC
public void Update(SettingViewModel Setting)
{
GS_SysConfig setting = new GS_SysConfig();
//might also just use a util function to convert to string based on the type of Value
setting.ConfigVal = Setting.Value.ToString(; //Value is not a field in the abstract class
db.SaveChanges();
}
This won't work because Value is not a field in the parent class, and I suppose I could come up with some way of doing casting and and getting types and such, but it seems messy and not very elegant. Is there a better approach to tryign to accomplish what I'm trying to do?
Update:
ConfigVal is of type String

C# implement interface with properties that are interface.

I am using EF code first to generate my db and I do need concrete property for ICollection of EF entity models. I am writing a data access layer ( Using generic classes) however hit the following road block with using interfaces in my generic class as shown below.
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass
{
ICollection<ITestClassProp> TestProp { get; set; }
}
public class TestClass : ITestClass
{
// works
//public ICollection<ITestClassProp> TestProp { get; set; }
// does not work
public ICollection<TestClassProp> TestProp { get; set; }
}
Am I totally mis using the interfaces? why cant I use TestClassProp instead of ITestClassProp?
Thanks
When you implement an interface, you have to implement the methods/properties of that interface with the same signature. Since the interface declares ICollection<ITestClassProp> TestProp { get; set; } then your TestClass must also declare ICollection<TestClassProp> TestProp { get; set; }.
The reason this is necessary is that other classes that know about the interface but not the concrete class are expecting the property to be ICollection<ITestClassProp> and not ICollection<TestClassProp>.
As you've currently written your code, you are not satisfying the requirement you've imposed via your ITestClass interface, which is to have a property of ICollection<ITestProp>.
One way around this is to actually make ITestClass generic, but provide a generic constraint of ITestClassProp
public interface ITestClassProp
{
int Value { get; set; }
}
public class TestClassProp : ITestClassProp
{
public int Value { get; set; }
}
public interface ITestClass<T> where T : ITestClassProp
{
ICollection<T> TestProp { get; set; }
}
public class TestClass : ITestClass<TestClassProp>
{
public ICollection<TestClassProp> TestProp { get; set; }
}
This allows you to provide any concrete type that implements ITestProp to your ICollection.
Simply, the interface declares a property of type ICollection, but you implement it as ICollection, which has a totally different signature.
You might want to read up on covariance and contravariance also.

C#, abstract superclass implementing a concrete variable defined by the subclass?

I have a system that performs operations on lots of Things, these can be considered to be hardware devices accessible over a communication channel.
I use a manager construct that accepts tasks for single Things. Now, there are at least three types of Thing and they have slightly different properties associated with them. The manager must know about these extra properties as they are needed to perform any operation correctly (some Things must have their X foo'd instead of their Y etc...).
At the moment I have separate manager class for each type of thing. This causes a good deal of duplication as the Things are mostly similar.
It would be good if I could have an abstract manager that implements a good deal of the functionality and then each concrete implementation can supply the little extra bits.
Here is a greatly simplified example:
public abstract class ThingManager
{
private ConcurrentDictionary<Guid, ??ThingTask??> _ThingTaskQueue;
public virtual AddNewThingTask(<params>)
{
??ThingTask?? NewTask = new ??ThingTask??(<params>);
_ThingTaskQueue.Add(NewTask);
Monitor.Pulse(_NewDataToProcess);
}
/* Implemented by the concrete, will depend on the type of ??ThingTask?? */
public abstract GetSomeTaskParameterForAThing(Guid thingID)
}
public class ThingTask
{
public enum ThingOperation
{
Foo,
Bar
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
}
public class AdvancedThingTask
{
public enum ThingOperation
{
Foo,
Bar,
Baz
};
public String Name { get; set; };
public ThingType Type { get; set; };
public ThingOperation Operation { get; set; }
public Boolean EnableFrobber { get; set; }
}
As you can see I need some way, when defining the concrete ThingManager to have ??ThingTask?? be either a ThingTask or an AdvancedThingTask. It would then be up to the concrete to make use of the extra properties when implementing the abstract methods.
Using an interface for ??ThingTask?? wouldn't work because the properties would have to be declared in the interface and each one has different properties available.
I get the feeling I'm missing something very obvious as to how to do this cleanly, hopefully someone can help :)
use generics rather than a pure abstract class, someting along the lines of:
public abstract class ThingManager<T> where T : ThingTask
dependant on your full implementation I doubt if this will need to remain abstract
Is there any reason you don't make AdvancedThingTask a subclass of ThingTask?
public class ThingTask
{
public virtual string Name { get; set; }
public virtual ThingType Type { get; set; }
public virtual ThingOperation Operation { get; set; }
public virtual void DoThing() { /*Do something associated with ThingTask*/ }
}
public class AdvancedThingTask : ThingTask
{
public bool EnableFrobber { get; set; }
public override void DoThing() { /*Do something associated with AdvancedThingTask*/ }
}
The only problem I see with this is that ThingOperation will need to be declared outside of the classes so that it can have all the values, or some other solution that will enable classes to have values that aren't in the base declaration. That problem may be solved by putting what you want to do as virtual methods in the classes.
P.S. Why do your properties start with underscores? Usually that's reserved for private variables.

Trouble defining an IList<T> where T is an generic interface

I am attempting to declare and use an interface like this:
public interface IItem<T>
{
string Name { get; set; }
T Value { get; set; }
}
This works fine until I attempt to create a list of these items. This fails to compile:
public interface IThing
{
string Name { get; }
IList<IItem<T>> ThingItems { get; }
}
so I am not certain where the issue is. The items value is not defined until runtime, and I need to have collections of the items. I figure that this is a fairly standard pattern, but I can not see where I am falling down.
Your class needs to be generic too (Thing<T>) or else the list can't know what type to use.
public interface Thing<T>
{
string Name { get; }
IList<IItem<T>> thingItems { get; }
}
EDIT
It compiles now.
EDIT
It seems you want your IItem<T> to be in terms of any type. This won't work in C#. You could create IList> here, but that is less than ideal, since you loose your typing when you want to get the items out.
You're falling down because the compiler wants to know what kind of items are in your list. So if you don't know yet, just create a non-generic base interface, and derive a generic more specific interface:
Maybe this helps you out:
public interface IItem
{
string Name { get; set; }
}
public interface IItem<T>: IItem
{
T Value { get; set; }
}
public interface IThing
{
string Name { get; }
IList<IItem> Items { get; }
}
public interface IThing<T>: IThing
{
string Name { get; }
IList<IItem<T>> Items { get; }
}
Interfaces cannot contain fields (data members)
A type containing a generic type is also a generic type
Two problems:
You can't declare fields in an interface. (rationale: a field is considered an implementation detail, which is the thing interfaces are designed to abstract away)
You can't have a generic field without specifying the type parameter (unless you have a type parameter on the declaring type too).
When you create an instace of Thing you have to know what the type of Thing.thingItems is. So the following is the correct way.
public interface Thing<T>
{
String Name { get; }
IList<IItem<T>> thingItems { get; }
}
If you do not know the concret type at the point of instanciating Thing you can only use a common base class or a common interface for the type.
public interface Thing<T>
{
String Name { get; }
IList<IItem<ThingParameterBase>> thingItems { get; }
}
Or with a common interface.
public interface Thing<T>
{
String Name { get; }
IList<IItem<IThingParameter>> thingItems { get; }
}

Categories