Accessing inherited members from static methods - Singleton Inheritance? - c#

Summary of the problem
Actually I just want to use normal inheritance functionality.
The catch is, that some of my methods are static, so they cannot access the inherited properties like normal.
Furthermore, I cannot pass anything to the static methods (like the instance of the object), because they are called by "external triggers".
On the other side I don't need multiple instances, meaning something like a singleton would be fine.
Let me explain you my situation step by step:
(Or just jump to the first code sample to see the MCV example)
Requirement 1 - Static methods accessing members
I'm using the library Harmony for patching methods of an existing Assembly.
The patching methods must be static and are called by the "hooks" of the library.
I add new player upgrades to a game. For each upgrade I want to patch I create a class with members, like name, description, image ...
One Upgrade must be only patched once, so the solution here would be making everthing static.
But ...
Requirement 2 - Inheritance
Because these upgrades share a lot of common members and methods, I make a BaseUpgrade class and derive from it.
Each specific implementation can now assign their values to the common fields like name, description ... and inherit the rest (the methods using the members).
Yet the members aren't accessible from the static patching methods anymore. For that I can use Singletons.
I want to inherit all the Singleton stuff too, making it generic. This way only the base class has all the Singeton code.
One approach would be this solution: https://stackoverflow.com/a/16865465
However ...
Requirement 3 - Having a Collection of the base class
I need to have collections of the base class and use them in dictionaries (both as key and value). But that doesn't seem to work with generic classes.
I found Collection of generic types, but I'm stuck. I don't know if incorporating this will actually work. At least it would complicate things even more.
Would that work? Is there maybe a much more simple approach to my problem?
MCV Example of the Basic Scenario
using System;
using System.Collections.Generic;
namespace Using_Singleton
{
// This is the version trying to incorperate the inheritable singleton
class Base<T> where T : Base<T>, new()
{
#region Singleton stuff
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
public string name; // Should be accessible by the derived class' static methods
public string desc;
protected Base()
{
name = "Base";
}
public void printName()
{
Console.WriteLine(name);
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("StaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("Name: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("StaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("Name 2x: " + Instance.name + " " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
//Dictionary<string, Base> itemDict; // ******* This is now broken
public Manager()
{
//itemDict = new Dictionary<string, Base>();
//Base addItem;
//addItem = new FirstChild();
//itemDict.Add(addItem.GetType().Name, addItem);
//addItem = new SecondChild();
//itemDict.Add(addItem.GetType().Name, addItem);
// Simulating the external call of one static method
SecondChild.StaticMethod_SecondChild();
Console.WriteLine();
}
public void DoSomething()
{
//foreach (var item in itemDict)
//{
// item.Value.printName();
//}
}
}
class Program
{
static void Main(string[] args)
{
Manager manager = new Manager();
manager.DoSomething();
Console.ReadLine();
}
}
}
Example using Inheritable Singletons
using System;
using System.Collections.Generic;
namespace Using_Singleton
{
// This is the version trying to incorperate the inheritable singleton
class Base<T> where T : Base<T>, new()
{
#region Singleton stuff
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
public string name; // Should be accessible by the derived class' static methods
public string desc;
protected Base()
{
name = "Base";
}
public void printName()
{
Console.WriteLine(name);
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("StaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("Name: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("StaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("Name 2x: " + Instance.name + " " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
//Dictionary<string, Base> itemDict; // ******* This is now broken
public Manager()
{
//itemDict = new Dictionary<string, Base>();
//Base addItem;
//addItem = new FirstChild();
//itemDict.Add(addItem.GetType().Name, addItem);
//addItem = new SecondChild();
//itemDict.Add(addItem.GetType().Name, addItem);
// Simulating the external call of one static method
SecondChild.StaticMethod_SecondChild();
Console.WriteLine();
}
public void DoSomething()
{
//foreach (var item in itemDict)
//{
// item.Value.printName();
//}
}
}
class Program
{
static void Main(string[] args)
{
Manager manager = new Manager();
manager.DoSomething();
Console.ReadLine();
}
}
}

After adding Inheritable Singletons to the small example I tried adding support for a generic collection, as suggested by Jon Saunders.
Basically making either an interface or class "above" the singleton class (the singleton class inherits it) and using this for the collection or in method parameters.
In this new non-generic class I've put all fields and methods. The constructors of the top non-generic class and the generic class are protected, so they cannot be instantiated.
Working solution
using System;
using System.Collections.Generic;
namespace Using_Singleton_And_GenericCollection
{
// This is the version trying to incorperate the inheritable singleton and a generic collection
abstract class NonGenericBase // Adding this (class or interface) make the use of collections possible.
{
public string name;
public string desc;
public void printName()
{
Console.WriteLine("\t" + name);
}
protected NonGenericBase() { }
}
class Base<T> : NonGenericBase where T : Base<T>, new()
{
#region Singleton stuff
protected static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
//public string name; // Moved to parent
//public string desc;
protected Base()
{
name = "Base";
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("\tStaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("\tName: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("\tStaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("\tName 2x: " + Instance.name + ", " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
public Dictionary<string, NonGenericBase> itemDict;
public Manager()
{
itemDict = new Dictionary<string, NonGenericBase>();
NonGenericBase addItem;
addItem = FirstChild.Instance;
itemDict.Add(addItem.GetType().Name, addItem);
addItem = SecondChild.Instance;
itemDict.Add(addItem.GetType().Name, addItem);
}
public void DoSomething()
{
foreach (var item in itemDict)
{
item.Value.printName();
}
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
var sec = new SecondChild();
Console.WriteLine("Access Singletons");
Manager manager = new Manager();
manager.DoSomething();
Console.WriteLine("Change Singletons");
manager.itemDict[nameof(FirstChild)].name = "first name changed";
SecondChild.Instance.name = "second name changed too";
manager.DoSomething();
Console.WriteLine("Create and change a non-Singleton instance of FirstChild");
var initItem = new FirstChild();
initItem.printName();
initItem.name = "Non-Singleton name changed";
initItem.printName();
Console.WriteLine();
Console.WriteLine("Access Singletons");
manager.DoSomething();
Console.WriteLine("Call static method of FirstChild");
FirstChild.StaticMethod_FirstChild(); //Simulating the external call of one static method
Console.WriteLine();
Console.ReadKey();
}
}
}
Output
Access Singletons
The first child
The second child
Change Singletons
first name changed
second name changed too
Create and change a non-Singleton instance of FirstChild
The first child
Non-Singleton name changed
Access Singletons
first name changed
second name changed too
Call static method of FirstChild
StaticMethod_FirstChild: I can access all member variables! :-)
Name: first name changed, Number: 7
Caveat
Because of the "new()" here
class Base<T> : NonGenericBase where T : Base<T>, new()
the constructors of the specific sub classes need to be public. This means that the Singletons aren't enforced, but "just" an option (see the output for an example).
BTownTKD states that in his answer he states that fact and links to his attempt to solve this via reflection an manually invoking private constructors here: Singleton.cs
Conclusion
Thanks to doing the MCV example for this question and trying it again with a greatly reduced complexity I've found the solution myself.
So this questioning process here and improving my initial post helped me with it. :-)

Related

Dependency Injection : Using Constructor Injection

Yesterday, One of my friends asked me to create a program(Must implement Dependency Injection) which return speed of the car. So, I have created a small program in which I tired to implement constructor injection.
class Program
{
static void Main(string[] args)
{
Maruti objMaruti = new Maruti();
clientClass obj = new clientClass(objMaruti);
obj.getSpeed();
}
}
public class clientClass
{
ISpeed _ISpeed;
public clientClass(ISpeed obj)
{
this._ISpeed = obj;
}
public int getSpeed()
{
return _ISpeed.Speed();
}
}
public interface ISpeed
{
int Speed();
}
public class Maruti : ISpeed
{
public int Speed()
{
return 200;
}
}
public class Audi : ISpeed
{
public int Speed()
{
return 400;
}
}
public class BMW : ISpeed
{
public int Speed()
{
return 600;
}
}
Now, In main Method, my friend can check speed of any car.
class Program
{
static void Main(string[] args)
{
Maruti objMaruti = new Maruti();
clientClass obj = new clientClass(objMaruti);
obj.getSpeed();
}
}
He asked me a question that why you have created this constructor Injection and client class. If you directly call the class, you would get the result.
class Program
{
static void Main(string[] args)
{
Maruti objMaruti = new Maruti();
objMaruti.Speed();
//If user wants to check Audi Speed.
Audi objAudi = new Audi();
objAudi.Speed();
}
}
Is he right? which way is best and why ?
I think the poor naming made your friend to ask you this question. What if you had the requirement to log the speed of different cars? The client class would have this name
public class SpeedLog
{
ISpeed speed;
ILogger logger;
public SpeedLog(ISpeed speed, ILogger logger)
{
this.speed = speed;
this.logger = logger;
}
public void Information()
{
logger.Information($"{speed.GetType().Name} is running with {speed.Speed()}");
}
}
This client class can log the speed of any object as long as the object has the Speed method in its public interface. The ISpeed interface gives us the opportunity to define the signature of the Speed method. Now the SpeedLog type doesn't depend on a particular type like Maruti or Audi or even a base type Car, if any, to retrieve the speed info. SpeedLog can now log the speed of stars if the Star type implements the ISpeed interface. When we add the new Star type we will only need to compile the library which contains this type and the library of the SpeedLog type remains untouched. An Inversion of Control library can now inject the Star object if it is asked to do so.

Restricted class factory design pattern

Is there an elegant (or any) way to achieve following in C#?
Let's have a class ItemBase (further derivable to Item1, Item2...), which does not allow direct instantiation (non-public construction) - to prevent user to create any 'untracked' instance of Item*.
Let's have a non-static class Manager, whose instances (multiple ones allowed) only can create and provide instances of Item* (because they keep track of produced instances and do some additional work).
Let's have an optional requirement: The Manager instances would like to manipulate non-public members of the managed Item instances (similar like the Manager would be a friend of Item*).
It would be nice if the Manager is not forced to be derivation of Item*.
It would be nice if there is as little reflection as possible.
Notes:
If possible, please consider this as a question raising from process of thinking how to implement particular problem solution in a best and elegant way. I would like it to be general and no, I don't have sources and yes, I have already tried some variants, but none of them satisfied my needs. Thank you.
As far as I know, there is no acceptable friend alternative (any of internal and InternalsVisibleToAttribute seems to be good), so the ItemBase just provides the 'special' (but public) modification methods and the user must be aware, these methods are not for him :o(
I like this solution, but I'm not able to invent, how to allow multiple Manager instances using it.
I think this might answer your problem :
public class ItemBase
{
protected ItemBase()
{
}
public void PublicMethod() { }
public int PublicProperty { get; set; }
}
public class Factory
{
private class PrivateItemBase : ItemBase
{
public void PrivateMethod() { }
public int PrivateProperty { get; set; }
}
public Factory(int id)
{
}
public IEnumerable<ItemBase> Items { get; private set; }
public ItemBase CreateItem()
{
PrivateItemBase rValue = new PrivateItemBase();
rValue.PrivateMethod();
rValue.PrivateProperty = 4;
return rValue;
}
}
Ok, giving up. If this might help to fully understand the purpose, there is the less bad solution I've (currently) ended up. Passing the creation functions is done via static constructors (which are not accessible by the users), unfortunately the ugly thing is their invocation...
Any idea how to make it better?
The item definitions:
namespace SpecialFactory
{
public enum ItemType
{
Item1,
Item2,
// ... Anyone deriving the Item* should add an item here
}
public abstract class ItemBase
{
public abstract ItemType Id {get;}
public static void RegisterAllCreators()
{
// Force static constructors invocation
var it = Item1.ClassId | Item2.ClassId; // Anyone deriving the Item* should ensure invocation of Manager.RegisterCreator
}
}
public class Item1 : ItemBase
{
static Item1()
{
Manager.RegisterCreator(ItemType.Item1, () => new Item1());
}
protected Item1()
{
}
public static ItemType ClassId => ItemType.Item1;
public override ItemType Id => ClassId;
}
public class Item2 : ItemBase
{
static Item2()
{
Manager.RegisterCreator(ItemType.Item2, () => new Item2());
}
protected Item2()
{
}
public static ItemType ClassId => ItemType.Item2;
public override ItemType Id => ClassId;
}
}
The manager:
namespace SpecialFactory
{
public class Manager
{
static Manager()
{
ItemBase.RegisterAllCreators();
}
protected static Dictionary<ItemType, Func<ItemBase>> creators = new Dictionary<ItemType, Func<ItemBase>>();
protected readonly List<ItemBase> managedItems = new List<ItemBase>();
protected ItemBase CreateItem(ItemType type)
{
ItemBase item = null;
if (creators.ContainsKey(type))
{
if ((item = creators[type]()) != null)
managedItems.Add(item);
}
return item;
}
public static void RegisterCreator(ItemType type, Func<ItemBase> creator)
{
if (!creators.ContainsKey(type))
creators[type] = creator;
}
public Manager()
{
}
public ItemBase Test(ItemType type)
{
// var notAllowed = new Item1();
var allowed = CreateItem(type);
return allowed;
}
}
}
The test:
namespace SpecialFactory
{
class Program
{
static void Main(string[] args)
{
var m1 = new Manager();
var m2 = new Manager();
var i1 = m1.Test(ItemType.Item1);
var i2 = m2.Test(ItemType.Item2);
}
}
}

Facing error in C# Generics Reference type constraint:'T' does not contain a definition for 'FooMethod'

public class Foo {
public Foo ThisX { get; set; }
public Foo ThisY { get; set; }
public Foo() {
}
public Foo(Foo x, Foo y) {
ThisX = x;
ThisY = y;
}
public void FooMethod(Foo ob) {
Console.WriteLine("Hiiiii\t" + ob);
}
}
public class Gen<T> where T : class {
T obj;
public Gen() {
}
public Gen(T x,T y) {
Console.WriteLine("Gen(T x,T y)\t" + x.GetType().Name + " " + y.GetType().Name);// + " " + obj.GetType().Name);
}
public void Display(T ob) {
obj = ob;
Console.WriteLine("Display " + ob.GetType().Name + " " + obj.GetType().Name);
obj.FooMethod(obj);
}
}
public class Program {
public static void Main(string[] args) {
Gen<Foo> m = new Gen<Foo>();
Foo ob1 = new Foo();
Foo ob2 = new Foo();
Console.WriteLine("Main " + m.GetType());
Console.WriteLine("Main " + ob1.GetType());
Console.WriteLine();
Gen<Foo> n = new Gen<Foo>(ob1, ob2);
Console.WriteLine();
m.Display(ob1);
}
}
The line "obj.FooMethod(obj)" giving an error saying
"'T' does not contain a definition for 'FooMethod' and no extension
method 'FooMethod' accepting a first argument of type 'T' could be
found (are you missing a using directive or an assembly reference?)"
Your answer is in the type constraint you gave in Gen
public class Gen<T> where T:class
At this point you are telling the compiler that T is going to be at least a class at the bare minimum. It may do more, but if definitely won't do less. In your definition you are telling the compiler that T is at least a class. A class is a generic thing that anyone can create which can do anything, but at its very least, it does nothing. The compiler understands the later and assumes that the bare minimum is an empty class as it can't guarantee a method, property, field, etc is always going to be there.
To get this to work we'll need to help the compiler a little bit with understanding what we want it to deal with. Your implementation of T has a common defintion, FooMethod. What happens inside of FooMethod? We don't care, and Gen doesn't care, we just want to execute it. What needs to happen is an abstract base class or an interface should be introduced for Gen to use as a constraint for T that way we at least have this method defined. After that we are going to implement this abstract base class (or interface) so that the compiler understands that we have a FooMethod defined.
The finalized code is below:
//abstract class to establish the presence of FooMethod, but not the functionality
public abstract class FooBase {
public abstract void FooMethod(FooBase obj);
}
//Implement FooBase so that Foo is guaranteed to have a FooMethod implementation
public class Foo : FooBase
{
public Foo()
{
}
public Foo(Foo x, Foo y)
{
ThisX = x;
ThisY = y;
}
public Foo ThisX { get; set; }
public Foo ThisY { get; set; }
//Override FooMethod so that it can do whatever Foo needs it to do
public override void FooMethod(FooBase ob)
{
Console.WriteLine("Hiiiii\t" + ob);
}
}
public class Gen<T> where T : FooBase
{
T obj;
public Gen()
{
}
public Gen(T x, T y)
{
Console.WriteLine("Gen(T x,T y)\t" + x.GetType().Name.ToString() + " " + y.GetType().Name.ToString());//+" "+obj.GetType().Name.ToString());
}
public void Display(T ob)
{
obj = ob;
Console.WriteLine("Display " + ob.GetType().Name.ToString() + " " + obj.GetType().Name.ToString());
//Fire the objests implementation of FooBase.FooMethod(FooBase obj)
obj.FooMethod(obj);
}
}
public class Program
{
public static void Main(string[] args)
{
Gen<Foo> m = new Gen<Foo>();
Foo ob1 = new Foo();
Foo ob2 = new Foo();
Console.WriteLine("Main " + m.GetType());
Console.WriteLine("Main " + ob1.GetType());
Console.WriteLine();
Gen<Foo> n = new Gen<Foo>(ob1, ob2);
Console.WriteLine();
m.Display(ob1);
//To stop the console
Console.ReadLine();
}
}
The issue that you're having is that the method FooMethod isn't a known method of class, so the generic Gen class is trying to call FooMethod within any class and failing. To get round this, the T type in Gen has to own a signature identical to the obj.FooMethod(obj); that is called from Gen
You can make this work in 2 ways, depending on what you're trying to acheive. If the Foo class is a base class, then the declaration for the Gen class to use the base class instead of class so:
public class Gen<T> where T:Foo
{
}
Or make an interface for Foo to implement:
public interface IFoo<T>
{
public void FooMethod(T ob)
{
}
}
class Foo : IFoo<Foo>
{
}
And tell your Gen class to use only classes that implement that interface:
public class Gen<T> where T:IFoo
{
}

How to override a type already registered in LightInject using a new instance passed to the constructor?

In repository I keep some instances which live throughout the lifetime of my application but sometimes I need an immediate replacement for such instance with another instance and LightInject even if passing the new instance to the container.GetInstance constructor override.
Here is a snippet showing the problem:
internal class ClassA
{
public string Name { get; private set; }
public ClassA(string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}
internal class ClassB
{
public ClassA A { get; private set; }
public ClassB(ClassA a)
{
A = a;
}
public override string ToString()
{
return string.Format("I contain {0}", A);
}
}
private void TestContainer()
{
var container = new LightInject.ServiceContainer();
var a1 = new ClassA("A instance 1");
container.Register(x => a1);
container.Register<ClassB>();
var a2 = new ClassA("A instance 2");
var bwitha1 = container.GetInstance<ClassB>();
if(bwitha1.A != a1)
{
throw new InvalidOperationException("This will not happen");
}
var bwitha2 = container.GetInstance<ClassA, ClassB>(a2);
if(bwitha2.A != a2)
{
throw new InvalidOperationException("Something went wrong here");
}
}
Why LightInject previously registered instance takes precedence if I give explicit instance in GetInstance call? How to get around the issue and construct the object with an alternative instance of one of the arguments?
In the current version of LightInject you need to provide a factory if you want to use runtime arguments.
The following workaround might work for you.
using LightInject;
class Program
{
static void Main(string[] args)
{
var container = new ServiceContainer();
container.Register<Bar>();
container.Register<Foo>();
container.Register<Bar, Foo>((factory, bar) => new Foo(bar), "FooWithRuntimeArgument");
var instance = container.GetInstance<Foo>();
var instanceWithRuntimeArgument = container.GetInstance<Bar, Foo>(new Bar(), "FooWithRuntimeArgument");
}
}
public class Foo
{
public Foo(Bar bar) {}
}
public class Bar {}

Using methods on Generics

I have a ton of methods like this:
public UIPCompanyButton AddCompanyButton (string name, Company company, UIEventListener.VoidDelegate methodToCall, GameObject contents)
{
return UIPCompanyButton.Create (name, company, methodToCall, contents);
}
that I'd like to replace with a single method like this:
public T AddButton<T,K>(string name, K item, UIEventListener.VoidDelegate methodToCall, GameObject contents) where T:UIPMenuButton
{
return T.Create(name, item, methodToCall, contents);
}
which obviously doesn't work at the T.Create part. Is there a certain syntax I need to do this?
I'm also open to a different method with the same result: a single method that takes in a derived menuButton and creates the right one with the right class of "item".
No, you can't call static methods on generic types - not without reflection. Aside from anything else, there's no way of constraining a generic type to have specific static members. The closest to that is the parameterless constructor constraint.
What you want is a factory to create your objects. Here is a small working example. It might not be the best way to implement a factory pattern, but it should get you going.
For a more in depth example and explanation, see this page.
public class Button {
public string Whatever { get; set; }
public Button() {
Whatever = "Hello, world!";
}
}
public interface IAddButton {
Button CreateButton();
}
public class ClassToMakeButtonFor1 {
public static void RegisterMe() {
ButtonFactory.Register(typeof(ClassToMakeButtonFor1), new ButtonFactory1());
}
}
public class ButtonFactory1 : IAddButton {
public Button CreateButton() {
return new Button();
}
}
public class ClassToMakeButtonFor2 {
public static void RegisterMe() {
ButtonFactory.Register(typeof(ClassToMakeButtonFor2), new ButtonFactory2());
}
}
public class ButtonFactory2 : IAddButton {
public Button CreateButton() {
var b = new Button { Whatever = "Goodbye!" };
return b;
}
}
public static class ButtonFactory {
private static Dictionary<Type, IAddButton> FactoryMap = new Dictionary<Type, IAddButton>();
public static void Register(Type type, IAddButton factoryClass) {
FactoryMap[type] = factoryClass;
}
public static Button MakeMeAButton<T>() where T : class {
return FactoryMap[typeof(T)].CreateButton();
}
}
internal class Program {
private static void Main(string[] args) {
ClassToMakeButtonFor1.RegisterMe();
ClassToMakeButtonFor2.RegisterMe();
Button b = ButtonFactory.MakeMeAButton<ClassToMakeButtonFor1>();
Console.WriteLine(b.Whatever);
b = ButtonFactory.MakeMeAButton<ClassToMakeButtonFor2>();
Console.WriteLine(b.Whatever);
Console.ReadLine();
}
}
What you could consider is to have some interface (e.g. ICreator) that defines a Create method you want to call.
Then you would constrain your type parameter to types that implement the interface ( where T : ICreator).
Then you would call the method on an instance, not a static method. So in your case maybe you could call item.Create(...).
Makes any sense for your case?
It sounds like you might be able to make your Button class generic. Depending on how much logic lives in each of these derived classes, this may not work for you.
class Button<T>
{
public T Item { get; private set; }
public Button(string name, T item, ...)
{
// Constructor code
}
}
// Helper class for creation
static class Button
{
public static Button<T> Create<T>(string name, T item, ...)
{
return new Button<T>(name, item, ...);
}
}
Then, to use this:
Button<Company> button = Button.Create("Name", company, ...);

Categories

Resources