How to create / create a class that can have different types of members at runtime in C #

I have a situation where I need a class that needs to contain information about something that changes at runtime, for example:

class Info<T>
{
    public T Max { get; set; }
    public T Min { get; set; }
    public T DefaultValue { get; set; }
    public T Step { get; set; }
    // Some other stuff
}

      

I need to store many instances of this class in a dictionary, but the problem is that in order to use the dictionary I have to declare one type, for example.

Dictionary<string, Info<int>> dict = new Dictionary<string, Info<int>>();

      

In this case, I cannot add another type of information, eg. Info<double>

... I want something like, I removed the shared version in the following case.

 {"Price", new Info{Min=100,Max=1000,DefaultValue=200,Step=50}}
 {"Adv", new Info{Min=10.50,Max=500.50,DefaultValue=20.50,Step=1.5}}
 {"Answer", new Info{Min=false,Max=false,DefaultValue=false,Step=false}}

      

I can use Dictionary<string, Object> dict = new Dictionary<string, Object>();

but then when i go back to the dict element i dont know what type it is, i need to know the type as well eg. for Price

it is int and for Adv it is double, how do I know it at runtime?

Actually I want to create a validator (I am using .Net Compact Framework 3.5 / cannot use the embedded system if it exists), for example if I have a class like below.

class Demo
{
    public int Price { get; set; }
    public float Adv { get; set; }

    public static bool Validate(Demo d)
    {
        List<string> err = new List<string>();
        // here I have to get Info about the Price
        // from dictionary, it can be any storage
        Info priceInfo = GetPriceInfo("Price");
        if (d.Price < priceInfo.Min)
        {
            d.Price = priceInfo.Min;
            err.Add("price is lower than Min Price");
        }
        if (d.Price > priceInfo.Max)
        {
            d.Price = priceInfo.Max;
            err.Add("price is above than Max Price");
        }
        // need to do similar for all kinds of properties in the class  
    }
}

      

So the idea is to store the validation data in one place (in a dictionary or somewhere else) and then use that information during validation, I would also like to know if I can better construct the above scenario?

Perhaps there is a better way to do this, please, any guidance?

+3


source to share


4 answers


You can use a base class that is not generic:

public abstract class Info {
}

public class Info<T> : Info {
}

      

Now all the different generic types inherit from the same base type, so you can use this in a dictionary:

Dictionary<string, Info> dict = new Dictionary<string, Info>();

      



You can define properties and methods where the interface is independent of the generic type in the base class and implements them in the generic class. This way you can use them without specifying a generic type.

For methods where you need a type, you need special code for each type. You can use the operators is

and as

to test type:

Info<int> info = dict[name] as Info<int>;
if (info != null) {
  int max = info.Max;
}

      

+4


source


Can you take from Microsoft and mimic the IEnumerable interface and create .Cast<T>

? However, someone will know about your type unless you want to get caught in dynamic

(4.0+ only) or reflection. Both of these come with a cost. Perhaps you need to rethink your design?



+1


source


Keith Nicholas is right - if you want your dictionary to support multiple types, you need an interface, but it must be generic .

Try something like this (warning: untested code):

interface IInfo<T>
{
    T Max { get; set; }
    T Min { get; set; }
    T DefaultValue { get; set; }
    T Step { get; set; }
}

Dictionary<string, IInfo> dict = new Dictionary<string, IInfo>();

class AnswerInfo : IInfo<bool> { }
class PriceInfo : IInfo<int> { }
class AdvInfo : IInfo<double> { }

dict["Answer"] = new AnswerInfo() { Min = false, Max = false, DefaultValue = false, Step = false };
dict["Price"] = new PriceInfo() { Min = 100, Max = 1000, DefaultValue = 200, Step = 50 };
dict["Adv"] = new AdvInfo() { Min = 10.50, Max = 500.50, DefaultValue = 20.50 Step = 1.5 };

      

0


source


Using a dictionary of objects (or some base class), you will have several options for accessing data (usually using some kind of inheritance from a common base class to work with it, which has the properties described below).

  • Use an enum to denote the type, then you might have some kind of switch / case. (Easy to do, not very C # ish.)
  • Use something similar to VARIANT. Variants are types that provide both the information they store and the stored value, which can be any basic type like string, int, float. (Doesn't actually exist in C #, as you can see from the answers here Variant type in C # .)
  • You can also check the type of an object at runtime to see what kind of object you have, then throw it and process its contents based on its type. (There are several ways .. you might need to use reflection, see first here: get the type of an object and assign values ​​accordingly .)
  • You could also try to abstract somehow the operation you want to do on each object and then call that function. Something like a command template. ( Command pattern: how to pass parameters to a command? )

Maybe many more. :)

0


source







All Articles