I met some interesting covariance problem in my c# code.
I have a generic Matrix
class, and it\'s been instantiated for example Matrix
Recently I've come across such limitation and I implemented a variation of Visitor Pattern (may be abuse of it). But that helped me to solve the problem.
I'm no architect, just a developer. So pardon me if am abusing the design pattern, but sure this will help.
With provided information I created mocks of your classes and applied visitor pattern as follows.
public class Matrix<T>
{
public T Obj { get; set; }
}
public interface INonGenericWrapper
{
void Wrap();
void Accept(IVisitor visitor);
}
public class Wrapper<T> : INonGenericWrapper
{
public Matrix<T> Matrix { get; private set; }
public void Wrap()
{
//Your domain specific method
}
public void Accept(IVisitor visitor)
{
visitor.Visit(this);
}
}
public interface IVisitor
{
void Visit<T>(T element);
}
public class SerializationVisitor : IVisitor
{
public void Visit<T>(T element)
{
new Serializer<T>().Serialize(element);
}
}
public class Serializer<T>
{
public Stream Serialize(T objectToSerialize)
{
Console.WriteLine("Serializing {0}", objectToSerialize);
//Your serialization logic here
return null;
}
}
How to use:
List<INonGenericWrapper> wrappers = new List<INonGenericWrapper>();
wrappers.Add(new Wrapper<object>());
wrappers.Add(new Wrapper<string>());
wrappers.Add(new Wrapper<int>());
var visitor = new SerializationVisitor();//Create the operation you need to apply
foreach (var wrapper in wrappers)
{
wrapper.Accept(visitor);
}
All you've to do is create a new visitor for each operation you need to perform.
Here is the Demo which outputs
Serializing Wrapper`1[System.Object]
Serializing Wrapper`1[System.String]
Serializing Wrapper`1[System.Int32]
You have said that you want to be able to insert data into the collection based on the covariantly exposed type. This is simply not possible. For a type to be covariant it needs to not expose any means of inserting data. The type would need to be contravariant to support that, but if the type is contravariant then it cannot expose the information in a covariant manor.
In short, this is impossible, and not just impossible because of what C# as a language has implemented, but impossible on a conceptual level. It's not possible to implement a statically typed solution to this problem in any conceivable language.