I want to instantiate a generic list of objects like:
public static class TablesClass
{
private static IList<Tables<T>> TablesInstance { get; set; }
static TablesClass() => Tables = new List<Tables<T>>();
public static void AddTable(Table<t> table) => Tables.Add(table);
}
I can't change Tables<T>, this is a nuget package class.
How may i achieve this? All i have tried just does not work (setting a type T to class, using object instead T and casts - not desired solution).
Can somebody help me?
TablesClass is not a generic class and you are not telling the compiler what type T is supposed to be somewhere.
If you want to be able to add different kinds of objects into the same IList<Tables<T>> list, T must be a common base type for all these objects.
For example, if you want to be able to add apples, pears and bananas to the list, the type parameter T may be specified as Fruit provided that Fruit is the base class for all these types.
Obviously you will need to cast from Fruit if you want to be able to access any member of an item in the list that is specific to a concrete implementation of Fruit class but this is inevitable. You don't throw a bunch of different kinds of fruits into a single basket and expect to be able to always pick up a specific fruit, do you?
Your nuget class must be this style:
public abstract class Tables
{
}
//the Generic class must has a base, by which you can list them
public class Tables<T> : Tables // where T: something base class of your object
{
//...
}
then your class must be:
public static class TablesClass
{
//Search source code of your Nuget package, find its base class of Generic class, the list must be defined as its base
private static IList<Tables> Tables { get; set; }
static TablesClass()
{
Tables = new List<Tables>();
}
public static void AddTable(Tables table)
{
Tables.Add(table);
}
}
then you can use it like this:
public class Test
{
public static void Mains()
{
TablesClass.AddTable(new Tables<A>());
TablesClass.AddTable(new Tables<B>());
TablesClass.AddTable(new Tables<C>());
}
}
If you want to do this kind of thing you need to hold the references using object, but make a method that allows you to store and fetch each table using strong-typing.
Try a class like this:
public class Repository
{
private Dictionary<Type, Dictionary<string, object>> _store
= new Dictionary<Type, Dictionary<string, object>>();
public void Store<T>(string key, T value)
{
if (!_store.ContainsKey(typeof(T)))
{
_store.Add(typeof(T), new Dictionary<string, object>());
}
_store[typeof(T)][key] = value;
}
public T Fetch<T>(string key)
{
return (T)_store[typeof(T)][key];
}
public bool TryFetch<T>(string key, out T value)
{
var success = _store.ContainsKey(typeof(T)) && _store[typeof(T)].ContainsKey(key);
value = success ? this.Fetch<T>(key) : default(T);
return success;
}
public bool TryInject<T>(string key, Action<T> inject)
{
var success = this.TryFetch<T>(key, out T value);
if (success)
{
inject(value);
}
return success;
}
}
Then you can strongly-type the objects into the repository (collection) and strongly-type fetching them out like this:
var repository = new Repository();
repository.Store("a", new TableA());
repository.Store("b", new TableB());
repository.Store("c", new TableC());
repository.Store("d", new TableD());
/* Somewhere else in your code */
TableA a = repository.Fetch<TableA>("a");
TableB b = repository.Fetch<TableB>("b");
TableC c = repository.Fetch<TableC>("c");
TableD d = repository.Fetch<TableD>("d");
The key value (i.e. "a") is optional - you can remove it from the code - but it is useful if you need to store more that one object of a specific type.
Way much simple solution: List<dynamic>.
Related
I would like to find out which of the properties in a source input object, a method has used. After executing the method I need to store in a database which of the properties was used.
The input could be any class with simple types, like this:
public class MyData : IMyData
{
public string A { get; set; }
public int B { get; set; }
public decimal C { get; set; }
}
I thought it could be done using an interface as input to the method, so I can replace the original object with a more advanced object, which stores usage of properties
public interface IMyData
{
string A { get; }
int B { get; }
decimal C { get; }
}
I can then
Create a dynamic object with the same properties
Use ImpromptuInterface to simulate the dynamic object implements my interface
Call my method with this dynamic interface
private static void Main()
{
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
IDictionary<string, object> replacementObject = new ExpandoObject();
replacementObject.Add("FieldsUsed", new List<string>());
foreach (var property in data.GetType().GetProperties())
replacementObject.Add(property.Name, property.GetValue(data));
var replacementInterface = replacementObject.ActLike<IMyData>();
DoStuff(replacementInterface);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)replacementObject["FieldsUsed"])}");
}
private static void DoStuff(IMyData source)
{
Console.WriteLine($"A is {source.A}");
if (source.B > 5)
Console.WriteLine($"C is {source.C}");
}
In the above example I would like to store that fields A and B have been used.
Only I am stuck at how I should store when a property is used by my DoStuff method.
You can write a wrapper like this:
public class ClassWrapper<T>: DynamicObject where T:class
{
private readonly T _obj;
private readonly List<string> _fieldsUsed=new List<string>();
public ClassWrapper(T obj)
{
_obj = obj;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
PropertyInfo propertyInfo = _obj.GetType().GetProperty(binder.Name);
_fieldsUsed.Add(binder.Name);
result = propertyInfo.GetValue(_obj);
return true;
}
public List<string> GetFieldsUsed() => _fieldsUsed;
public T GetWrapper()
{
return this.ActLike<T>();
}
}
and use it like
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
var mc=new ClassWrapper<IMyData>(data);
IMyData wrapped = mc.GetWrapper();
DoStuff(wrapped);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)mc.GetFieldsUsed())}");
If you want to know when a property is used, a Interface like INotifyPropertyChanged can do that for you at runtime. The exampel is only about notification for writes (that actually changed a value), but it would be trivial to expand it to reads and writes. It is not a perfect thing of course, as different executions might follow different code paths that use different properties.
If a function takes a specific type as input, you have to asume that all properties may be relevant. This is especially true for abstract types and interfaces - often the interface exists for this function. If it is one of those two, you can also always provide your own implementation of those Interfaces and Abstract class.
I can not shake the feeling that this is a XY problem.
Hi I have a simple issue with an sql application that I seem not to be capable of resolve. It involves the use of generics of which I am not too familiar with. I did researches here and on-line but I do not seem to find a fitting solution for my case.
I have two classes: Table and Field. I want Table to contain a List of Field and I want each Field to contain a List of RecordSet. The tricky part is that I want the user to choose which type of RecordSet to implement.
The Class Definition of Table is:
namespace DBlib
{
public class DBTable<T>
{
public List<DBField<T>> FieldName = new List<DBField<T>>();
public DBTable (string NameOfTable)
{
}
public void AddField (string Name)
{
DBField<T> TempList = new DBField<T>();
FieldName.Add(TempList);
}
}
}
The Class Definition of Field is:
namespace DBlib
{
public class DBField<T>
{
public List<T> RecordSet = new List<T>();
public DBField()
{
}
}
}
With this code the user is forced cast the type when he is instantiating DBTable. This is not correct. I want the user to cast the type when the AddField method is invoked. Can you suggest a simple way to solve this issue?
UPDATE #1
I changed TempList as DBField in the Table Class definition. Sorry for the confusion there.
I want to add also this code to explain better what my issue is. Assuming the first Field of the table is an integer, the user should do:
namespace SpecifytheName
{
public class User
{
DBTable<int> Table = new DBTable<int>();
public User()
{
}
}
}
Instead, I want the user to do:
namespace SpecifytheName
{
public class User
{
DBTable Table1 = new DBTable("Table1");
// SPECIFY THE TYPE OF FIELD1 ONLY AT THIS POINT
Table1.AddField<int>("Field1"); //or something like this
public User()
{
}
}
}
I would generally solve this issue using a non-generic interface to store your fields.
So start with this interface:
public interface IDBField
{
IList RecordSet { get; }
Type FieldType { get; }
}
Now implement DBField<T> like this:
public class DBField<T> : IDBField
{
public List<T> RecordSet = new List<T>();
IList IDBField.RecordSet
{
get
{
return this.RecordSet;
}
}
Type IDBField.FieldType
{
get
{
return typeof(T);
}
}
}
Then you can implement DBTable like this:
public class DBTable
{
public List<IDBField> FieldName = new List<IDBField>();
public void AddField<F>(string Name)
{
FieldName.Add(new DBField<F>());
}
}
You can use the FieldType property on IDBField to determine the type of the field and then use reflection as necessary to use the values of RecordSet appropriately.
The only way I can see this working is by not using Generics, but just use the Object class.
for example:
public class DBTable
{
public List<DBField<Object>> FieldName = new List<DBField<Object>>();
public DBTable (string NameOfTable)
{
}
public void AddField(string Name)
{
List<DBField<Object>> TempList = new List<DBField<Object>>();
FieldName.Add(TempList);
}
}
This will mean you can use any type in the RecordSet object without restricting the type in the DBTable class.
I could be a bit off base here as I'm not sure what you're trying to achieve, for one you aren't going anything with the Name parameter passed into the AddField method, and you're TempList object isn't the same type as FieldName so it should throw some errors there..
EDIT:
I think I understand more clearly what you're trying to do, try this -
public class DBTable
{
public List<DBField<Object>> FieldName = new List<DBField<Object>>();
public DBTable (string NameOfTable)
{
}
public void AddField<FieldType>(string Name)
{
DBField<FieldType> field = new DBField<FieldType>(Name);
FieldName.Add(field);
}
}
This way each Field (Column) is still forced to a type, but the DBTable isn't tied down to that same type.
I have a set of classes, each of which can open different types of files using an external application and tell that application to print the file to a particular printer. The classes all inherit a common abstract class and an interface.
internal interface IApplicationPrinter : IDisposable
{
string ApplicationExe { get; }
string ApplicationName { get; }
string[] PrintableExtensions { get; }
IApplicationPrinter CreateInstance(string Filename, string Printer);
void Print();
bool ExitApplicationAfterPrint { get; set; }
bool WaitApplicationExitOnPrint { get; set; }
System.IO.FileInfo PdfFile { get; protected set; }
}
internal abstract class ApplicationPrinter : IApplicationPrinter
{
...
}
internal class WordPrinter : ApplicationPrinter
{
internal static string[] PrintableExtensions { get { return new string[]{".doc", ".docx" }; } }
...
}
internal class ExcelPrinter : ApplicationPrinter
{
internal static string[] PrintableExtensions { get { return new string[]{".xls", ".xlsx" }; } }
...
}
I am trying to create a Dictionary of printable file extensions and corresponding Types of classes that can print such files. I do not want to instantiate the classes in the dictionary.
private static Dictionary<string, Type> FileConverters;
static Printer()
{
FileConverters = new Dictionary<string, Type>();
foreach (string ext in WordPrinter.PrintableExtensions)
{
FileConverters.Add(ext, typeof(WordPrinter));
}
string filename = "textfile.txt";
string extension = filename.Substring(filename.LastIndexOf("."));
if (FileConverters.ContainsKey(extension))
{
IApplicationPrinter printer = ((IApplicationPrinter)FileConverters[extension]).CreateInstance(filename, "Printer");
printer.Print();
}
}
Is there any way to make Dictionary<string, Type> FileConverters more type-safe, by restricting it to values that implement IApplicationPrinter? In other words, is something like this possible:
private static Dictionary<string, T> FileConverters where T: IApplicationPrinter;
Update:
I do not want to store instances for the following two reasons:
Each class can handle several different file types (see string[] PrintableExtensions). The dictionary stores extensions as keys. There is no utility in creating and storing multiple separates instance of the same class.
Each printer class uses COM API and Office Interop to create instances of third-party applications. It's better that a new instance of each class is created for a print job when so required, and that the garbage collector can clean up afterwards.
I would do it slightly differently:
private Dictionary<String, Func<IApplicationPrinter>> _converters;
public void Initialise()
{
foreach (string ext in WordPrinter.PrintableExtensions)
{
_converters.Add(ext, () => new WordPrinter());
}
}
public IApplicationPrinter GetPrinterFor(String extension)
{
if (_converters.ContainsKey(extension)) //case sensitive!
{
return _converters[extension].Invoke();
}
throw new PrinterNotFoundException(extension);
}
This method will not store instances in the dictionary as you require, and will create you a new instance each time you call GetPrinterFor. It also is more strongly typed as the return type of the Func<> has to be an IApplicationPrinter.
Not directly - remember that the things you're putting in your dictionary are Type objects, not objects that implement IApplicationPrinter.
Probably the best option here is to check that each type you add to your dictionary implements IApplicationPrinter, by checking whether type.GetInterface("IApplicationPrinter") returns null or not.
If you used Dictionary<string, IApplicationPrinter>, that doesn't necessary mean you will have to have different instance for each string, several of them can share the same instance.
If you don't want to do that, you can store factories in the dictionary. The factory can be an object that implements an interface (something like IApplicationPrinterFactory), or just a delegate that can create the object. In your case, that would be Dictionary<string, Func<IApplicationPrinter>>. Doing it this way is completely type-safe. To add to the dictionary, you would do something like:
FileConverters = new Dictionary<string, Func<IApplicationPrinter>>();
Func<IApplicationPrinter> printerFactory = () => new WordPrinter();
foreach (string ext in WordPrinter.PrintableExtensions)
FileConverters.Add(ext, printerFactory);
If you're sure you want Dictionary<string, Type>, there is no way to limit that, so that all types in there implement IApplicationPrinter. What you could do is to create your own dictionary, that checks the type upon addition. This doesn't make compile-time safe, but it makes it more runtime-time safe.
class TypeDictionary : IDictionary<string, Type>
{
private readonly Type m_typeToLimit;
readonly IDictionary<string, Type> m_dictionary =
new Dictionary<string, Type>();
public TypeDictionary(Type typeToLimit)
{
m_typeToLimit = typeToLimit;
}
public void Add(string key, Type value)
{
if (!m_typeToLimit.IsAssignableFrom(value))
throw new InvalidOperationException();
m_dictionary.Add(key, value);
}
public int Count
{
get { return m_dictionary.Count; }
}
public void Clear()
{
m_dictionary.Clear();
}
// the rest of members of IDictionary
}
First you need to change your approach to access the extensions array because you can't access your property without creating a instance. I would use a custom attribute to tell your type-dictionary which extension each class supports. This will look like this:
[PrinterExtensions("txt", "doc")]
public class WordPrinter
{
.... // Code goes here
}
Using the attribute allows you to restrict the type. There are two ways to archive this.
Throw a exception in the constructor of the type ( see this link )
Use a abstract class instead of a interface, this allows you restrict you class by using a protected attribute ( at this point you need to create a base class for the attribute to access it from your type-dictionary ) which can only be applied to devired classes.
Now you can just can just check if a particular class has the PrinterExtensions attribute and access a property of it which retrieves all the extensions or call a method which directly registers all extensions.
I have a set of custom data types that can be used to manipulate basic blocks of data. For example:
MyTypeA Foo = new MyTypeA();
Foo.ParseString(InputString);
if (Foo.Value > 4) return;
Some of these types define read-only properties that describe aspects of the types (for example a name, bit size, etc.).
In my custom framework I want to be able to provide these types to the user for use in their applications but I also want to give the user a list of the available types which they could easily bind to a combobox. My current approach:
public static class DataTypes
{
static ReadOnlyCollection<MyDataType> AvailableTypes;
static DataTypes()
{
List<MyDataType> Types = new List<MyDataType>();
Types.Add(new MyTypeA());
Types.Add(new MyTypeB());
AvailableTypes = new ReadOnlyCollection<MyDataType>(Types);
}
}
What concerns me about this is that the user might obtain a type from the AvailableTypes list (by selecting a combobox item for example) and then use that reference directly rather than creating a clone of the type and using their own reference.
How can I make the list of available types read only so that it doesn't allow any writing or changes to the type instances, forcing the user to create their own clone?
Alternatively is there a better way of providing a list of available types?
Thanks, Andy
Make your custom Type class immutable, same as System.Type and you dont have to worry. A end user can fetch all the data it wants but he can not modify the object in any way.
EDIT: Example of immutable class
Take the following class for instance:
public class ImmutablePerson
{
private readonly string name; //readonly ensures the field can only be set in the object's constructor(s).
private readonly int age;
public ImmutablePerson(string name, int age)
{
this.name = name;
this.age = age;
}
public int Age { get { return this.age; } } //no setter
public string Name { get { return this.name; } }
public ImmutablePerson GrowUp(int years)
{
return new ImmutablePerson(this.name, this.age + years); //does not modify object state, it returns a new object with the new state.
}
}
ImmutablePerson is an immutable class. Once created there is no way a consumer can modify it in any way. Notice that the GrowUp(int years) method does not modify the state of the object at all, it just returns a new instance of ImmutablePerson with the new values.
I hope this helps you understand immutable objects a little better and how they can help you in your particular case.
To get around the problems you've mentioned, you could create a wrapper around your instances, and have the wrapper provide the functionality you require.
For example:
public class TypeDescriptor
{
private MyDataType _dataType;
public TypeDescriptor(MyDataType dataType)
{
_dataType = dataType;
}
public override string ToString()
{
return _dataType.ToString();
}
}
You class would then look something like:
public static class DataTypes
{
public static ReadOnlyCollection<TypeDescriptor> AvailableTypes;
static DataTypes()
{
List<TypeDescriptor> Types = new List<TypeDescriptor>();
Types.Add(new TypeDescriptor(new MyTypeA()));
Types.Add(new TypeDescriptor(new MyTypeB()));
AvailableTypes = new ReadOnlyCollection<TypeDescriptor>(Types);
}
}
Binding to the list and relying on the ToString() will now result in your data types ToString being called.
Create a list of types rather than a list of instances. e.g.
List<Type> Types = new List<Type>();
Types.Add(typeof(MyTypeA));
Types.Add(typeof(MyTypeB()));
etc.
To answer the comment on binding to a drop down list:
MyDropDown.Datasource = Type.Select(t => t.Name);
MyDropDown.DataBind();
This will not use the custom property of your classes but it will give you the simple calss name without all the other guff e.g. MyTypeA
A collection cannot "inject" type modifiers into its members. The collection you have declared is readonly. If you want MyDataType to be readonly you must declare that way.
Somthing like :
EDIT extended class to have a parse method
public class MyDataType
{
private MyDataType()
{
...
}
internal static MyDataType Parse(string someString)
{
MyDataType newOne = new MyDataType();
newOne.Value = ... //int.Parse(someString); ?
}
public int Value { get; private set; }
}
If the collection stays generic there is no readonly constraint.
You would use it like this, following your example.
MyTypeA foo = MyTypeA.Parse(inputString);
if (foo.Value > 4) return;
You probably shouldn't store instances of your types in the list. Instead you can store types. These can be used to create instances:
public static class DataTypes
{
static ReadOnlyCollection<Type> AvailableTypes;
static DataTypes()
{
List<Type> Types = new List<Type>();
Types.Add(typeof(MyTypeA));
Types.Add(typeof(MyTypeB));
AvailableTypes = new ReadOnlyCollection<MyDataType>(Type);
}
}
You can use Activator.CreateInstance to create a concrete instance:
Object myType = Activator.CreateInstance(AvailableTypes[0]);
Unless your types share a common base type you cannot downcast the result and an Object isn't that useful.
Also the use of the term type in your code makes my example a bit confusing as I suggest you store the types of something called type.
You could consider creating and attribute that you then can apply to MyTypeA, MyTypeB etc. Then you can build the AvailableTypes using reflection and the list will always be up to date with your code. E.g. if you add MyTypeC and use the attribute it will automatically be added to the list.
You can also add a display string property to the attribute and use that for display in the combo box. If you want to do that you should store a small object combining the type and the display string in AvailableTypes.
Here is an example. Using generic words like type and data can be confusing so to pick a random name I just use foo. Obviously you should use a more descriptive name.
[AttributeUsage(AttributeTargets.Class, Inherited = false)]
sealed class FooAttribute : Attribute {
public FooAttribute(String displayName) {
DisplayName = displayName;
}
public String DisplayName { get; private set; }
}
You can decorate you classes using this attribute:
[Foo("Type A")]
class MyTypeA { ... }
[Foo("Type B")]
class MyTypeB { ... }
For the combobox you want a list of factory objects with a nice ToString implementation (this class can be improved by adding some error handling which I have left out to save space):
class FooFactory {
readonly Type type;
public FooFactory(Type type) {
this.type = type;
DisplayName = ((FooAttribute) Attribute.GetCustomAttribute(
type,
typeof(FooAttribute))
).DisplayName;
}
public String DisplayName { get; private set; }
public Object CreateFoo() {
return Activator.CreateInstance(this.type);
}
public override String ToString() {
return DisplayName;
}
}
Returning Object from CreateFoo isn't very useful but that is a separate issue.
You can build this list at run-time:
var factories = Assembly
.GetExecutingAssembly()
.GetTypes()
.Where(t => Attribute.IsDefined(t, typeof(FooAttribute)))
.Select(t => new FooFactory(t));
I'm not exactly sure of what you want but should something like this be ok ?
public static class DataTypes
{
static Dictionary<string,Type> AvailableTypes
= new Dictionary<string,Type>()
{
{ "MyTypeA", MyTypeA },
{ "MyTypeB", MyTypeB },
...
};
}
That is actually return types instead of sample instances of theses types. Thus you would be sure that only new instances would be created by the user of your class.
Then in the calling code :
MyTypeA a = Activator.CreateInstance(DataTypes.AvailableTypes["MyTypeA"]);
Greetings everyone!
I'll try to make my problem simple: I have an enum to select which ObjType I should use (ObjTypeA and ObjTypeB both inherits from ObjType). So I created a method to extend the given enum, in order to return a new instance according to the selected property in the enum, like follows in the code. I think it works more or less like a factory design pattern. So far so good, but eventually, like in the class MyClass, I may attempt to create n instances of ObjTypeA or ObjTypeB, but I'll have to face the if statement everytime I call the GetObjTypeInstance() method. So:
Can an enum return an instance, something like: public enum EObjType { ObjTypeA = new ObjTypeA(), ObjTypeB = new ObjTypeB() }? Actually, it'd be better to append some GetInstance() method to the ObjTypeA and to the ObjTypeB options in the enum. If there's a way to do this, how can I do it? Doing this I'd avoid those if statements every while step.
Is there any other (and better) way to this this (if you understood my problem...)? How?
Thanks in advance!
Follow the example code:
public static class EObjTypeExt
{
public static ObjType GetObjTypeInstance(this EObjType ot)
{
if (ot == EObjType.ObjTypeA)
{
return new ObjTypeA();
}
else if (ot == EObjType.ObjTypeB)
{
return new ObjTypeB();
}
throw new ArgumentOutOfRangeException("unrecognized type!");
}
}
public enum EObjType { ObjTypeA, ObjTypeB }
public class MyClass
{
ObjType[] obj { get; set; }
public MyClass(EObjType otEnum, int n)
{
this.obj = new ObjType[n];
int i = 0;
while (i < n)
{
this.obj[i] = otEnum.GetObjTypeInstance();
i++;
}
}
}
You'll have to byte this apple somewhere.
Maybe replace the if/elseif chain with switch statement, they work great with enums.
Instead of using an enum, I would use a class that looks like an enum:
public class EObjType {
public static readonly EObjType ObjTypeA = new EObjType(() => (ObjType)(new ObjTypeA));
public static readonly EObjType ObjTypeB = new EObjType(() => (ObjType)(new ObjTypeB));
private readonly Func<ObjType> generator;
private EObjType(Func<ObjType> generator) {
this.generator = generator;
}
public ObjType GetInstanceOfObjType() {
return generator();
}
}
You can then use it exactly as you have been the enum.
EObjType otEnum = EObjType.ObjTypeA;
ObjType obj = otEnum.GetInstanceOfObjType();
You need to use a factory or other creational design pattern.
For instance, you could hold a dictionary from enum key to type value to get the desired class type using selected enum value. Then use reflection to create a new instance (object) of received type.
Initialize static dictionary's values using static constructor of factory class. You can enter the values manually or better yet, load possible values from a config file.
I'm not sure that I'd really advocate this approach, but you could call the enum ToString() method, treat that as your class name and use reflection to instantiate an object of that type.
One advantage of this would be that you could reflect and get the type once, then call the constructor n times in your loop.
As Danny Varod points out, a dictionary mapping your enum values to their Types (or to functions that create those types) would allow you to avoid if statements. Since enum is really just an integer underneath, an array would be more memory and time efficient, but readability is probably most important here.
You could create a factory that allows registration of functions that map to your enumeration, you could that use some sort of registration process to register your different enumerations
public class ObjectFactory
{
private readonly Dictionary<MyObjectType, Func<MyObject>> _store = new Dictionary<MyObjectType, Func<MyObject>>();
public void Register<T>(MyObjectType type) where T: MyObject, new()
{
this.Register(type, () => new T());
}
public void Register(MyObjectType type, Func<MyObject> factory)
{
_store.Add(type, factory);
}
public MyObject CreateInstance(MyObjectType type)
{
Func<MyObject> factory;
if(_store.TryGetValue(type, out factory))
{
return factory.Invoke();
}
return null;
}
}
public enum MyObjectType { A, B }
public class MyObject {}
public class MyObjectA : MyObject {}
public class MyObjectB : MyObject {}
Usage as follows
var factory = new ObjectFactory();
factory.Register<MyObjectA>(MyObjectType.A);
factory.Register<MyObjectB>(MyObjectType.B);
var a = factory.CreateInstance(MyObjectType.A);
var b = factory.CreateInstance(MyObjectType.B);
Assert.IsInstanceOf(typeof(MyObjectA), a);
Assert.IsInstanceOf(typeof(MyObjectB), b);
You could use Activator.CreateInstance.
public class ObjType {}
public class ObjTypeA : ObjType {}
public class ObjTypeB : ObjType {}
public enum EObjType { ObjTypeA, ObjTypeB }
public static class EObjTypeExt
{
public static ObjType GetObjTypeInstance( EObjType ot)
{
object o = Activator.CreateInstance(null,ot.ToString());
return (ObjType)o;
}
}