General type conversion

I am having serious design issues due to generic issues. Maybe someone has some suggestions.

EDIT: So, I know that this is usually not done, but I completely changed my sample code because I realized that the original pseudocode did not really explain my problem. The following code is much more like the real example I'm dealing with. Hope my problem will be clearer. I apologize for being a little long, but from my experience, generic problems usually come up when you try to build a more complex structure. So:

class Program
    {
        static void Main(string[] args)
        {
            IConnector<IService> connector = ConnectorBuilderFactory.NewBuilder<IService>("someEndpoint").MakeReliable().GetConnector();
            connector.Connect();
        }
    }

    public interface IService : IConnectionMaintainable
    {
        void DoSomething();
    }

    public interface IConnectionMaintainable
    {
        DateTime GetServerTime();
    }

    public interface IConnector<T>
    {
        T Channel { get; }
        void Connect();
        void Disconnect();
    }

    public interface IConnectorBuilder<T>
    {
        IConnector<T> GetConnector();
        IConnectorBuilder<T> MakeReliable();
        // ...more connector-configuration methods
    }

    public class ChannelWatchDog<T> where T : IConnectionMaintainable
    {
        private IConnector<T> connector;

        public ChannelWatchDog(IConnector<T> connector /*various other parameters*/)
        {
            this.connector = connector;
        }

        // ...methods that use connector Connect, Disconnect, and GetServerTime methods
    }

    public class Connector<T> : IConnector<T>
    {
        private T channel;

        public Connector(string endpoint)
        {
            // ...build channel
        }

        public T Channel
        {
            get { return channel; }
        }

        public void Connect()
        {
            // ...connect to server
        }

        public void Disconnect()
        {
            // ...disconnect from server
        }
    }

    public class ConnectorBuilder<T> : IConnectorBuilder<T>
    {
        private string endpoint;

        public ConnectorBuilder(string endpoint)
        {
            this.endpoint = endpoint;
        }

        public IConnector<T> GetConnector()
        {
            Connector<T> connector = new Connector<T>(endpoint);

            // If reliability was requested, build the ChannelWatchDog: Following line does not compile:
            // ChannelWatchDog<T> watchDog = new ChannelWatchDog<T>(connector);

            return connector;
        }

        public IConnectorBuilder<T> MakeReliable()
        {
            // save various parameters required to build the ChannelWatchDog
            return this;
        }
    }

    public static class ConnectorBuilderFactory
    {
        public static IConnectorBuilder<T> NewBuilder<T>(string endpoint)
        {
            return new ConnectorBuilder<T>(endpoint);
        }
    }

, -, GetConnector ConnectorBuilder, , , . . , , :

  • (ChannelWatchDog), IConnector. IConnector, IConnector, IConnector, GetServerTime IConnectionMaintainable.

  • , , Expression Builder ( IConnectionBuilder). , IConnector, IConnector <IConnectionMaintainable> . T IConnectorBuilder , ChannelWatchDog. , , GetConnector. MakeReliable .

, , , , , -, , -, . , ChannelWatchDog ConnectorBuilder :

public class ChannelWatchDog
    {
        private IConnector<IConnectionMaintainable> connector;

        public ChannelWatchDog(IConnector<IConnectionMaintainable> connector /*various other parameters*/)
        {
            this.connector = connector;
        }

        // ...methods that use connector Connect, Disconnect, and GetServerTime methods
    }

    public class ConnectorBuilder<T> : IConnectorBuilder<T>
    {
        private string endpoint;

        public ConnectorBuilder(string endpoint)
        {
            this.endpoint = endpoint;
        }

        public IConnector<T> GetConnector()
        {
            Connector<T> connector = new Connector<T>(endpoint);

            // If reliability was requested, build the ChannelWatchDog: Following line does not compile:
            ChannelWatchDog watchDog = new ChannelWatchDog((IConnector<IConnectionMaintainable>)connector);

            return connector;
        }

        public IConnectorBuilder<TReliable> MakeReliable<TReliable>() where TReliable : T, IConnectionMaintainable
        {
            // save various parameters required to build the ChannelWatchDog
            return (IConnectorBuilder<TReliable>)this;
        }
    }

IConnector .

, . , :) , .

, , ConnectorBuilders ( ReliableConnectorBuilder) factory factory. .

EDIT: : IConnector ConnectionBuilder, , IConnectionMaintainable .

+5
6

?

GenericClass<IFoo> wrapper = new GenericClass<IFoo>(new FooImplementor());
Acceptor acceptor = new Acceptor(wrapper);
+5

GenericClass, Covarianz. . . , , , :

class GenericClass<out T> { ... }
+1

, Connector<T> Connector<IConnectionMaintainable>, , , Connector<T>.

public class Connector<T> : IConnector<T>
{
    // ...
    private Connector()
    {
    }
    // ...
    public static explicit operator Connector<IConnectionMaintainable>(Connector<T> other)
    {
        Connector<IConnectionMaintainable> connector = null;

        Type p = typeof(T);
        if (p.GetInterfaces().Contains(typeof(IConnectionMaintainable)))
        {
            connector = new Connector<IConnectionMaintainable>();
            connector.channel = other.channel as IConnectionMaintainable;
        }
        else
        {
            throw new InvalidCastException();
        }

        return connector;
    }
}

public class ConnectorBuilder<T> : IConnectorBuilder<T>
{
    // ...
    public IConnector<T> GetConnector()
    {
        Connector<T> connector = new Connector<T>(endpoint);

        // If reliability was requested, build the ChannelWatchDog:
        try 
        {
            Connector<IConnectionMaintainable> temp = (Connector<IConnectionMaintainable>)connector;
            ChannelWatchDog<IConnectionMaintainable> watchDog = new ChannelWatchDog<IConnectionMaintainable>(temp);
        }
        catch (InvalidCastException)
        {
            throw new ArgumentException("Trying to make reliable when not possible");
        }

        return connector;
    }
    // ...
}
+1

GenericClass<T> / / , .NET. /, Type .

0

, :

// If reliability was requested, build the ChannelWatchDog: Following line does not compile:
        ChannelWatchDog watchDog = new ChannelWatchDog((IConnector<IConnectionMaintainable>)connector);

,

ChannelWatchDog watchDog = new ChannelWatchDog(connector);

, , , IConnector :

public interface IConnector<T> where T:IConnectionMaintainable
{
    T Channel { get; }
    void Connect();
    void Disconnect();
}

This is from the hip, and hopefully gives an idea or clues. The restriction compiles according to linqpad.

This also leads to cascading restriction requirements, so here is the rest of the code that compiles:

void Main()
{

}

// Define other methods and classes here
  public interface IConnectionMaintainable
{
    DateTime GetServerTime();
}

public interface IConnector<T> where T:IConnectionMaintainable
{
    T Channel { get; }
    void Connect();
    void Disconnect();
}

 public interface IConnectorBuilder<T> where T:IConnectionMaintainable
{
    IConnector<T> GetConnector();
    IConnectorBuilder<T> MakeReliable();
    // ...more connector-configuration methods
}
public class ChannelWatchDog
{
    private IConnector<IConnectionMaintainable> connector;

    public ChannelWatchDog(IConnector<IConnectionMaintainable> connector /*various other parameters*/)
    {
        this.connector = connector;
    }

    // ...methods that use connector Connect, Disconnect, and GetServerTime methods
}

public class ConnectorBuilder<T> : IConnectorBuilder<T> where T:IConnectionMaintainable
{
    private string endpoint;

    public ConnectorBuilder(string endpoint)
    {
        this.endpoint = endpoint;
    }
    public IConnectorBuilder<T> MakeReliable()
    {
        // save various parameters required to build the ChannelWatchDog
        return this;
    }
    public IConnector<T> GetConnector()
    {
        Connector<T> connector = new Connector<T>(endpoint);

        // If reliability was requested, build the ChannelWatchDog: Following line does not compile:
        ChannelWatchDog watchDog = new ChannelWatchDog((IConnector<IConnectionMaintainable>)connector);

        return connector;
    }

    public IConnectorBuilder<TReliable> MakeReliable<TReliable>() where TReliable : T, IConnectionMaintainable
    {
        // save various parameters required to build the ChannelWatchDog
        return (IConnectorBuilder<TReliable>)this;
    }
}

 public class Connector<T> : IConnector<T> where T:IConnectionMaintainable
{
    private T channel;

    public Connector(string endpoint)
    {
        // ...build channel
    }

    public T Channel
    {
        get { return channel; }
    }

    public void Connect()
    {
        // ...connect to server
    }

    public void Disconnect()
    {
        // ...disconnect from server
    }
}
0
source

You must make a generic parameter T in the ConnectorBuilder class to implement the IConnectionMaintainable interface. The reason for this is because it is needed for the generic ChannelWatchDog type. Generic T is not strict enough for a type parameter of type ChannelWatchDog.

0
source

All Articles