简体   繁体   中英

C# dynamic field depending on “T” type, without hardcoding

So I have a function. It takes in an object called 'item' of an unknown type. In the function, it declares an object, and depending on what the Type is, depends on what field of 'item' the object gets a value from, for example:

private static void CreateObject<T>(T item)
{
    SomeObject object = new SomeObject();

    //if 'item' is type "A"
    //          object.Text = item.Display
    //else if 'item' is type "B"
    //          object.Text = item.Text
    //else if 'item' is type "C"
    //          object.Text = item.Value


}

Please note, passing the string of 'item.display' or which ever is not an option, as alot goes on in this function, and this is a simplified version of the function for explaining whats required.

How could this be done in a more elegant way?

I have looked at reflection but been instructed to avoid this as it is expensive (hardware, memory etc)

Take a delegate parameter that will provide the Text

private static void CreateObject<T>(T item, Func<T, object> prop)
{
    SomeObject obj = new SomeObject();

    obj.Text = prop(item).ToString();
}

So the caller of the method will use

CreateObject(a, t => t.Display);
CreateObject(b, t => t.Text);
// etc

You could apply the adapter pattern and pass in an adapter object that will return display text and other things. That object can be constructed by the caller as appropriate (presumably, the caller will know more about the nature of the object it is sending in to CreateObject() ). Examples:

interface IMyAdapter {
    string GetDisplayText();
    // ...
}

class TextBoxAdapter : IMyAdapter {
    private readonly TextBox tb;

    public TextBoxAdapter(TextBox tb) {
        this.tb = tb;
    }

    public string GetDisplayText() {
        return tb.Text;
    }

    // ...
}

...

public static void CreateObject(IAdapter adapter) {
    SomeObject obj = new SomeObject();
    obj.Text = adapter.GetDisplayText();
    // ...
}

...

var textBoxAdapter = new TextBoxAdapter(new TextBox());
CreateObject(textBoxAdapter);

In addition to Eranga's answer about passing a delegate, if you do not want to litter delegates all over your calling code you could create non-generic overloads for this function to do it for you.

private static void CreateObject<T>(T item, Func<T, string> prop) {
  SomeObject obj = new SomeObject();
  obj.Text = prop(item);
}

private static void CreateObject(TypeA item) {
  CreateObject(item, i => i.Display);
}

private static void CreateObject(TypeB item) {
  CreateObject(item, i => i.Text);
}

This would centralise the delegates, while still pulling it away from the middle of the body of your function.

I think to give the "best" answer though, we would need to know a lot more about the size and purpose of this method, where it is being called from etc.

There are many ways you could approach this, and honestly under some circumstances there would be nothing wrong with your series of if statements. It is clear, any programmer should understand it and if you only have a couple of cases just do it and get on with solving real problems.

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