简体   繁体   中英

How do I write an adapter class to simulate an interface on primitive types?

I have a method that takes in an interface. I wrote out a custom function for each primitive type (and string). Here's what it looks like:

public interface IFoo
{
    void DoSomething();
}

static void IntDoSomething(int value)
{
    // do something with an int, as if it implemented IFoo
}

static void FloatDoSomething(float value)
{
    // do something with a float, as if it implemented IFoo
}

// ... I have an XDoSomething() for all the other primitives and string

public void Execute(IFoo value)
{
    value.DoSomething();
}

public void Execute(int value)
{
    IntDoSomething();
}

public void Execute(float value)
{
    FloatDoSomething();
}
// ... I have an Execute() for all the other primitives and string

While tedious, having an Execute() for each primitive type is workable. The problem is when I have to add stuff like these:

public void Execute(List<IFoo> values)
{
    foreach (IFoo foo in values)
    {
        values.DoSomething();
    }
}

public void Execute(Dictionary<IFoo, IFoo> values)
{
    foreach (var pair in values)
    {
        pair.Key.DoSomething();
        pair.Value.DoSomething();
    }
}

Do I have to write out an Execute() function every time I have a new collection I want to process? For the dictionary one, I'd have to explicitly define versions for every combination of every primitive!

I feel like there's a solution involving writing an adapter class that wraps up primitives to be IFoos, but I can't seem to do it without breaking the method signature of Execute(). I don't want the user to have to create an adapter first, I want it to happen implicitly. Is there any way to do that?

Thanks!

I might be misunderstanding, but could you do something like this? Hopefully this isn't what you're trying to avoid... You'd have to write an adapter for each primitive, but at least you'd be able to do your collection executes

public inteface IFoo
{
    void DoSomething();
}

public IntFoo : IFoo
{
    private int _value;

    public IntFoo(int value)
    {
        _value = value;
    }

    void DoSomething()
    {
        IntDoSomething(_value);
    }
}

Two options come to mind;

One would be having DoSomething take an object so that any value would work, and you could use the "is" operator on the parameter to determine the type. This is obviously not very typesafe.

Also, as you mentioned, you could make DoSomething a generic function. Then, in the implementation you could use:

public void Execute<T>( T value) 
{
    if( value is int )
    {
        IntDoSomething();
    }
    else if( value is float)
    {
        FloatDoSomething();
    }
}

etc.

Again, not very typesafe, so you might want to validate the input at the top of the method.

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