Multiple generic types in one container - c#

I was looking at the answer of this question regarding multiple generic types in one container and I can't really get it to work: the properties of the Metadata class are not visible, since the abstract class doesn't have them. Here is a slightly modified version of the code in the original question:
public abstract class Metadata
{
}
public class Metadata<T> : Metadata
{
// Per Ben Voigt's comments, here are the rest of the properties:
public NUM_PARAMS NumParams { get; set; }
public FUNCTION_NAME Name { get; set; }
public List<Type> ParamTypes { get; set; }
public Type ReturnType { get; set; }
//...C
public T Function { get; set; }
public Metadata(T function)
{
Function = function;
}
}
List<Metadata> metadataObjects;
metadataObjects.Add(new Metadata<Func<double,double>>(SomeFunction));
metadataObjects.Add(new Metadata<Func<int,double>>(SomeOtherFunction));
metadataObjects.Add(new Metadata<Func<double,int>>(AnotherFunction));
foreach( Metadata md in metadataObjects)
{
var tmp = md.Function; // <-- Error: does not contain a definition for Function
}
The exact error is:
error CS1061: 'Metadata' does not
contain a definition for 'Function' and no
extension method 'Function' accepting a
first argument of type 'Metadata'
could be found (are you missing a
using directive or an assembly
reference?)
I believe it's because the abstract class does not define the property Function, thus the whole effort is completely useless. Is there a way that we can get the properties?
Update
The basic idea is that I have a genetic program that uses the Metadata of functions (or MetaFunctions) in order to construct expression trees with those functions. The meta data allows me to correctly match the return from one function with the input parameters of another function... it basically turns my functions into legos and the computer can combine them in various ways. The functions are all within the same "domain", so I won't have any problem with randomly mixing and matching them.
I'm storing the Metadata, or MetaFunctions, into a couple of dictionaries:
one has the name of the function as the key.
the other has the number of parameters as the key.
In any case, I just tried to stick as close to the original question as possible... the fundamental problem is the same regardless if I use a List or a Dictionary. I'm also stuck with .NET 3.5 and I won't be able to update to .NET 4.0 for a while.

What would you do with md.Function if you could read it? You can't call it, because you don't know the parameter types. With C# 4.0, you could use dynamic, e.g. foreach (dynamic md in metadataObjects) and then you don't need the Metadata abstract base class. If you just want to access members of Delegate, you could change the abstract base class to an interface which has a Delegate Metadata { get; } property and explicitly implement it in Metadata<T>, then you could access e.g. the function's name.

I think the main problem here is that you are trying to solve a very Dynamic problem with the very Static (but flexible) tools of Generic Programming. So i see two ways for you to go.
Split all your collections along type boundaries, creating a different collection for each type of function you have. This should be possible in your case because you know all the types ahead of time so you will know what types to create.
Embrace the dynamic nature of the problem you are trying to solve and then use the right tools for the job. From what I can tell you want to be able to store a list of 'Functions' and then dynamically decide at run time which ones to call with which arguments. In this case you just need a better model.
I would go with option 2. From my understanding I think that this would be a better model.
public class Variable
{
public Type Type {get; protected set;}
public Object Value {get;protected set;}
public Variable(Object val)
{
Type = val.GetType();
Value = val;
}
public Variable(Type t, Object val)
{
Type = t;
Value = val;
}
}
public class ComposableFunction
{
public NUM_PARAMS NumParams { get; protected set; }
public FUNCTION_NAME Name { get; protected set; }
//our function signature
public List<Type> ParamTypes { get; protected set; }
public Type ReturnType { get; protected set; }
private Delegate Function { get; set; }
public Metadata (Delegate function)
{
Function = function;
}
public bool CanCallWith(params Variable vars)
{
return CanCallWith(vars);
}
public bool CanCallWith(IEnumerable<Variable> vars)
{
using(var var_enum = vars.GetEnumerator())
using(var sig_enum = ParamTypes.GetEnumerator())
{
bool more_vars = false;
bool more_sig =false;
while( (more_sig = sig_enum.MoveNext())
&& (more_vars = var_enum.MoveNext())
&& sig_enum.Current.IsAssignableFrom(var_enum.Current.Type));
if(more_sig || more_vars)
return false;
}
return true;
}
public Variable Invoke(params Variable vars)
{
return Invoke(vars);
}
public Variable Invoke(IEnumerable<Variable> vars)
{
return new Variable(ReturnType, Function.DynamicInvoke(vars.Select(v => v.Value)));
}
}
So now we have a nice model that should fulfill your requirements, and because it takes no generic type parameters you should be able to access all of its functionality when you iterate through a List<ComposableFunction> or whatever.

you are right, the error is because the list thinks it has a bunch of Metadata objects so when you iterate it you get back metadata references, in order to access a property defined in a subclass you need to make sure that the object actually is that subclass and then do the cast.
foreach( Metadata md in metadataObjects)
{
var tmp =((Metadata<Func<double,double>>)md).Function; // but this will obviously fail if the type is incorrect.
}
so here you are really just trading a definite compile time error for a potential run time error (depending on what is in your list). The real question is: What do you want to do with all these different function delegate wrappers? what do you expect the type of your tmp variable to be?
You could also try a type testing solution like this
foreach( Metadata md in metadataObjects)
{
var dd_md = md as Metadata<Func<double,double>>;
var id_md = md as Metadata<Func<int,double>>;
var di_md = md as Metadata<Func<double,int>>;
if(dd_md != null)
{
var tmp1 =dd_md.Function;
}
else if(id_md != null)
{
var tmp2 =id_md.Function;
}
else if(di_md != null)
{
var tmp3 =di_md.Function;
}
//etc....
}
this could also be a viable solution as long as you know exactly what types there will be ahead of time, but its annoying and error prone.

Related

Inferring generics from parent class in method signature fails

I'm using a library with (hundreds of, template-generated) classes without generic modifier, each extending the same classes with generic modifier (essentially to shorten the notation). E.g.
class DArr : NumberObject<double, MyArrayIndexer> { ... }
class IArr : NumberObject<int, MyArrayIndexer> { ... }
class DMat : NumberObject<double, MyMatrixIndexer> { ... }
class IMat : NumberObject<int, MyMatrixIndexer> { ... }
class BMat : NumberObject<bool, MyMatrixIndexer> { ... }
and so on
I now want to write functions that proccess these with a function that requires their internal type (e.g. internal copies that need to know whether we have 4 or 8 bytes per element, and what type of Indexer is being used). I therefore made the signature of my function:
public SomeUnrelatedClass<T> Process<T,TVal,T0>(SomeUnrelatedClass<T> obj) where T : NumberObject<TVal,T0> {
//here some tstuff that requires T, TVal and T0
}
but unfortunately it seems I can't use it in the way I need to, i.e.
SomeUnrelatedClass<DArr> input = ...;
SomeUnrelatedClass<DArr> output = Process(input);
since it fails to derive TVal and T0 from (why??), despite it being uniquely determined. How can I remedy this? Calling it as SomeUnrelatedClass<DArr> output = Process<DArr,double,MyArrayIndexer>(input); is not an option because in reality there's a lot more of these generics and they're a lot longer in name (and this function will be used thousands of times in future code, so I'd much rather now write a more complicated function that does it right and keeps the syntax simple). Ideally I'd not do a long list of "if type == ..." though, because the list of types is template-generated and changes over time as types get added (meaning this template would be dependent on the other template, etc.)
I've thought of silly hacks like making the syntax Process<T,TVal,T0>(SomeUnrelatedClass<T> obj,SomeUnrelatedClass<NumberObject<TVal,T0>> sameObj) and calling SomeUnrelatedClass<DArr> output = Process(input,input); but I feel like that's just a really poor fix. What's a more 'proper' way to do this?
I think you might be in some luck here, because C# does not infer types based on the constraints that you specify. I think it's part of the specification, from what I could dig out. But you might be able to solve you problem anyway :) - I managed to get the following running.
{
var input = new DArr(12.34);
var output = Visitor.Process(input);
Console.WriteLine($"Type [{output.Obj.GetType()}] with value {output.Obj.MyType}");
}
{
var input = new IArr(42);
var output = Visitor.Process(input);
Console.WriteLine($"Type [{output.Obj.GetType()}] with value {output.Obj.MyType}");
}
// Generated output:
//
// Type [DArr] with value 12,34
// Type [IArr] with value 42
So no matter how many types you define that Process method will consume and map the input to the right concrete type.
Below is how this could work:
public class NumberObject<TType, TIndexer>
{
public NumberObject(TType type) { MyType = type; }
public TType MyType { get; }
}
public class MyArrayIndexer { }
public class DArr : NumberObject<double, MyArrayIndexer>
{
public DArr(double value) : base(value) { }
}
public class IArr : NumberObject<int, MyArrayIndexer>
{
public IArr(int value) : base(value) { }
}
public class SomeUnrelatedClass<T>
{
public T Obj { get; }
public SomeUnrelatedClass(T obj){ Obj = obj; }
}
public class Visitor
{
public static SomeUnrelatedClass<NumberObject<TVal, T0>> Process<TVal, T0>(NumberObject<TVal, T0> input)
{
return new SomeUnrelatedClass<NumberObject<TVal, T0>>(input);
}
}
The trick here is to reduce the number of generic parameters - getting rid of the T type as it can directly be expressed by the remaining two as you actually also write yourself
T is NumberObject<TVal, T0>
When the level of types to infer is reduced the C# compiler can determine them directly and viola you can leave you specifying generic parameters to the Process method.

Cast Action<T1> to Action<T2> in c# where T1 and T2 have no relation

I've got two objects which (Domain and Data) which in this case have the same property (let's presume Name). I've got an Action<DomItem> which I would like to cast to Action<DataItem>.
public class DomItem {
public string Name { get; set; }
}
public class DataItem {
public string Name { get; set; }
}
public class Program {
public Program() {
Action<DomItem> domAction = new Action<DomItem>(x=>x.Name = "Test");
// Something Casted To Action<DataItem>(x=>x.Name = "Test");
}
}
Of course this is just a basic example. It's by design that I can NOT use a common interface. I do not care about the DataItem might not be having the same property.
I've been looking into Expressions and several other solutions but I just can't figure out how to create the Cast (or get the "x=>x.Name =..." part from the method).
Any help would be really appreciated!
You can't directly or indirectly cast a Action<DomItem> to an Action<DataItem>, but you could wrap the action with a converter that converts the input from a DataItem to a DomItem and runs the original action on the copy:
public Action<DataItem> Convert(Action<DomItem> action)
{
return new Action<DataItem>(o => action(Map(o)));
}
public DomItem Map(DataItem dataItem)
{
return new DomItem{Name = dataItem.Name};
}
The obvious downside is that the action will be applied to a copy of the original object and not the original object itself. Without knowing exactly what the action is I don't know of a way to "cast" the action without a common base type.

How to create a list of dictionary objects of unknown value type?

I'm creating a CInformation class that will include various types of information. One type of the information it will expose are Parameters. Each parameter can be typed with any of the following types: int, short, string. Additionally, any parameter may have several possible values based on a string key. So I thought of creating a Dictionary<string, T> to hold all possible values for a parameter, but the problem arises when I try to declare my Parameters list. I created the following classes:
public class CParameter<T>
{
public object ParameterType { get; set; }
public Dictionary<string,T> ValueByString;
}
public class CInformation
{
public string Version { get; set; }
public string Name{ get; set; }
public List<CParameter<object>> Parameters; // cannot cast any of my types to object, obviously!
}
Any suggestions how I could get around my issue? I open to different solutions to my problem, not necessarily the same design I have above. Thank you.
EDIT: The main feature I want to achieve is to be able to have a list of dictionaries of different value types.
Using object to specialize a generic type is rather suspicious. If you do that, you might as well not even use a generic type at all. :-)
I think the issue here is that you want your instances of CParameter<T> to be specialized for different parameter types, and you want the parameters list on the CInformation class to contain different kinds of CParameter<T>.
In other words:
namespace Scratch
{
class Program
{
static void Main(string[] args)
{
CParameter<int> ints = new CParameter<int>();
CParameter<long> longs = new CParameter<long>();
CInformation info = new CInformation();
info.AddParameter(ints);
info.AddParameter(longs);
CParameter<int> ints2 = info.GetParameter<int>();
// ints2 and ints will both refer to the same CParameter instance.
}
}
public class CParameter<T>
{
public Type ParameterType { get { return typeof(T); } }
public Dictionary<string, T> ValueByString;
}
public class CInformation
{
public string Version { get; set; }
public string Name { get; set; }
private List<object> parameters;
public CInformation()
{
this.parameters = new List<object>();
}
public void AddParameter<T>(CParameter<T> parameter)
{
this.parameters.Add(parameter);
}
public CParameter<T> GetParameter<T>()
{
foreach (object parameter in this.parameters)
{
if (parameter is CParameter<T>)
return (CParameter<T>)parameter;
}
throw new Exception("Parameter type " + typeof(T).FullName + " not found.");
}
}
}
Note that the List<object> in that example could just as well be an ArrayList.
Also, I have a hunch that you're going to want to retrieve those CParameter objects by name rather than just by type. So consider adding a Name property to CParameter, and a name parameter to the GetParameter method. Then iterate over the list to find the property with the right name. Casting the result before returning it will verify that the type is the one you expected.
Or better yet, store the parameters in a Dictionary<string,object> instead of just a list, and use the parameter names as keys.

Can't understand C# Generics

I'm able to understand C# Generics but only when I read about it in a book where the examples are easy to follow. But in real life I get to see complicated C# Generics code like below. Can someone explain to me the generic aspects of this code? I see the type parameter but don't understand why the T is not used in the body of the method. How is the T being used in the body?
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )
{
if (response.CommunicationResponseCodes != null && response.CommunicationResponseCodes.Any())
{
var validateResult = new ValidationResults();
foreach (var communicationResponseCodeDataContract in response.CommunicationResponseCodes)
{
validateResult.AddResult( new ValidationResult(communicationResponseCodeDataContract.Description.Current, null, null, null, null));
}
throw FaultManager.GenerateFault(validateResult);
}
if( response.MessageError != null )
{
throw FaultManager.GenerateFault(eErrorCodes.Claims, response.MessageError.Current);
}
}
Here is a snippet for BaseClaimResponseDataContract:
[KnownType(typeof(SummaryClaimsReportResponseDataContract))]
[KnownType(typeof(ClaimResponseDataContract))]
[KnownType(typeof(CommunicationResponseDataContract))]
[DataContract]
public class BaseClaimResponseDataContract<T>
{
[DataMember]
public bool IsRxClaim { get; set; }
[DataMember]
public ThirdPartyDataContract ThirdParty { get; set; }
[DataMember]
public ExternalSystemMessages RequestMessage { get; set; }
[DataMember]
public bool RequestAccepted { get; set; }
[DataMember]
public string ResponseStatus { get; set; }
[DataMember]
[StringLength(10)]
public string ResponseCodes { get; set; }
[DataMember]
public string[] ResponseCodesArray
{
get
{
var lstMessageCodes = new List<string>();
if (!string.IsNullOrEmpty(ResponseCodes))
{
for (int i = 0; i < ResponseCodes.Length / 2; i++)
{
var code = ResponseCodes.Substring(i*2, 2);
if (!string.IsNullOrWhiteSpace(code))
lstMessageCodes.Add(code);
}
}
return lstMessageCodes.ToArray();
}
}
[DataMember]
public IEnumerable<CommunicationResponseCodeDataContract> CommunicationResponseCodes;
[DataMember]
public StringDataContract MessageError { get; set; }
public void CopyFrom(BaseClaimResponseDataContract<T> claimResponse)
{
IsRxClaim = claimResponse.IsRxClaim;
ThirdParty = claimResponse.ThirdParty;
RequestMessage = claimResponse.RequestMessage;
RequestAccepted = claimResponse.RequestAccepted;
ResponseStatus = claimResponse.ResponseStatus;
ResponseCodes = claimResponse.ResponseCodes;
CommunicationResponseCodes = claimResponse.CommunicationResponseCodes;
MessageError = claimResponse.MessageError;
}
}
In this situation, it seems the only purpose of the generic argument is to enforce that the parameter to the method must be a BaseClaimResponseDataContract<T>. I suspect multiple types in your solution inherit from this, for example:
public class SomeSample : BaseClaimResponseDataContract<AnotherClass>
{
}
The method can only be called with instances that implement this base type, so it's like a form of marking classes with an interface.
The method was made generic because it takes a generic argument. In order to specify the type of the argument a generic is used which means the method much take a generic argument itself.
In the case, it's not the method so much that's generic: it's the argument. The method is generic simply so that it can accept a type that is generic. You don't need to use the T argument within the method, because it's enough to know about the BaseClaimResponseDataContract part.
Usually, generics are used to conserve type information and flow it around. You get the same type out of a list that you put in.
In your case that is not apparent. T seems to be unused except to close the generic type.
Maybe BaseClaimResponseDataContract<T> has no useful non-generic base class. You can't use an open generic type, so you have to close it with a generic type parameter.
It doesn't matter whether T is used in the method or not. We can have a generic function like this:
int dummy<T> (List<T> a)
{
return a.Count * 2;
}
As you can see, T is not used anywhere in the method.Your example might also be something like this. Read on if you need more explanation:
Look at it this way: you have a generic type, and you want to write a method which takes a parameter of such a type, here BaseClaimResponseDataContract<>. Now, you can either write different methods, each for a concrete instance of this type, e.g.
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<int> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<float> response )
{ ... }
public void ValidateExceptionFromResponse( BaseClaimResponseDataContract<String> response )
{ ... }
which of course in not efficient, or let the method be a generic one, i.e. can take instances of BaseClaimResponseDataContract<> made from all types. Let's call this type T, then we can write
public void ValidateExceptionFromResponse<T>( BaseClaimResponseDataContract<T> response )

Derived interface from generic method

I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks
Sunit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T and FabInfo both implement IVirtualInterface does not mean you can perform a cast between the two types. For example if T is CoatInfo, then it is not compatible type with FabInfo.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T.
You can get around this error by first casting to object before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}

Categories

Resources