As I see it you have two options. The easy option is to expose the value (as an object) on the interface (and possibly its type as well). Here's how that would look:
interface ISomeClass
{
object ValueINeed { get; set; }
// Only needed if you care about static type rather than using ValueINeed.GetType()
Type TypeOfValue { get; }
}
class SomeClass<T> : ISomeClass
{
public T ValueINeed { get; set; }
public Type TypeOfValue { get { return typeof(T); } }
object ISomeClass.ValueINeed { get { return ValueINeed; } set { ValueINeed = (T)value; } }
}
This has the disadvantage that there's a bit of casting going on and you might need to invoke reflection to do certain things with the value. It has the advantage that it's easy to understand and implement.
The other alternative would be to encode an "existential type" which truly represents a SomeClass<T>
for some unknown T
(like a SomeClass<?>
in Java). This is much more complicated and hard to follow, but avoids any casts:
interface ISomeClassUser<X>
{
X Use<T>(SomeClass<T> s);
}
interface ISomeClassUser
{
void Use<T>(SomeClass<T> s);
}
interface ISomeClass
{
X Apply<X>(ISomeClassUser<X> user);
void Apply(ISomeClassUser user);
}
class SomeClass<T> : ISomeClass
{
public T ValueINeed { get; set; }
public X Apply<X>(ISomeClassUser<X> user) { return user.Use(this); }
public void Apply(ISomeClassUser user) { user.Use(this); }
}
// Assumes you want to get a string out, use a different generic type as needed
class XmlUser : ISomeClassUser<string>
{
public string Use<T>(SomeClass<T> s)
{
string str = "";
// do your conditional formatting here, branching on T as needed
// ...
return str;
}
}
class ClassThatHasListOfGenericObjects
{
List<ISomeClass> _l = new List<ISomeClass>();
XmlUser user = new XmlUser();
public string SomeMethod()
{
string s = "";
foreach (ISomeClass i in _l)
{
s += i.Apply(user);
}
return s;
}
}