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 )
Related
I get an object back from a method. The object is of type object and I can't change this because of backwards compatibility. If it is of a certain type (Response<T> bellow) then I need to access the property Payload which is of type T so that I can serialize it as part of a another object and send it off. The problem is that since I don't know the type of T I can't cast the object to Response<T> to access Payload even though I don't care about its type.
Here is my object with the generic type:
public class Response
{
public int Status { get; set; }
public string Message { get; set; }
}
public class Response<T> : Response
{
public T Payload { get; set; }
}
Here is what I would like to do:
// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
var payload = ((Response<object>)data).Payload; // Unable to cast object of type...
}
But the only way I could find to do this is by using dynamics.
// Will sometimes be of type Response<T>
object data = LegacyCode();
if (data.GetType().IsGenericType && data.GetType().GetGenericTypeDefinition() == typeof(Response<>)) {
var payload = ((dynamice)data).Payload;
}
Don't ask why things are the way they are (I'm wondering that myself). I have to do code gymnastics to keep backwards compatibility in this system. I just want compile time checking on the name of the property.
Here is a fiddle: https://dotnetfiddle.net/dXxHbD
UPDATE:
I need to be able to serialize and deserialize this object. Originally Response had a property Payload of type object. This caused serialization issues when Response<T> was deserialized because the Payload property was of type Newtonsoft.Json.Linq.JObject which could not be cast to T. Here is an example: https://dotnetfiddle.net/uc15HD
The problem was that I was going the wrong direction and the deserialization works if I cast T to object rather than try to cast object to T. When I store the value as its specific type T then the serializer knows what to deserialize the string to.
Here is an example using Jon's answer below: https://dotnetfiddle.net/KwudAx
Here is a similar example using Matias' solution of using covariance: https://dotnetfiddle.net/kCjZr4
To get compile-time checking of the name of the property, you can keep the dynamic typing, but get the runtime "mini-compiler" to do the hard work:
object data = LegacyCode();
object payload = GetPayload(data);
// Use payload
...
private static object GetPayload<T>(Response<T> response)
{
return response.Payload;
}
public static object GetPayload(object data)
{
// Fallback method. You could return null here and use
// that to indicate in the calling code that it wasn't a
// Response<T>...
}
A much better solution would be to add an non-generic interface or an extra base class though. For example:
public class Response
{
public int Status { get; set; }
public string Message { get; set; }
}
public interface IPayloadHolder
{
public object Payload { get; }
}
public class Response<T> : Response, IPayloadHolder
{
public T Payload { get; set; }
// By using explicit interface implementation, this
// doesn't get in the way for normal usage.
IPayloadHolder.Payload { get { return Payload; } }
}
Then you can use:
var payloadHolder = data as IPayloadHolder;
if (payloadHolder != null)
{
var payload = payloadHolder.Payload;
}
I believe that you need to use covariance.
Design an interface IResponse<out T>:
public interface IResponse<out T>
{
public T Payload { get; }
}
And implement it on Response<T>. Now you can cast it to IResponse<object>:
Response<string> x = new Response<string>();
IResponse<object> y = x; // implicit cast
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.
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.
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.
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();
}