简体   繁体   中英

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 (eg 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, ...);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM