Let's say I have a generic List<ICalculation> which serves as a repository for all predefined calculations in my application...
I have a generic interface called ICalculation<T, U> which implements the more basic ICalculation.
public interface ICalculation
{
string Identifier { get; }
object Calculate(object inputData);
}
public interface ICalculation<in TIn, out TOut> : ICalculation
{
string Identifier { get; }
TOut Calculate(TIn inputData)
}
I also have an abstract class CalculationBase that implements this interface
public abstract class CalculationBase<TIn, TOut> : ICalculation<in TIn, out TOut>, ICalculation
{
public abstract string Identifier { get; }
public abstract Func<TIn, TOut> Calculation { get; }
public virtual TOut Calculate(TIn inputData)
{
return Calculate(inputData, Calculation);
}
virtual object ICalculation.Calculate(object inputData)
{
return (TOut)calculation((TIn)inputData);
}
public static TOut Calculate(TIn inputData, Func<TIn, TOut> calculation)
{
if (calculation == null || inputData == null)
return default(TOut);
return calculation(inputData);
}
}
So, now I have a whole bunch of calculations that implement CalculationBase that function over some input... one example:
public sealed class NumberOfBillableInvoices : CalculationBase<IClientAccount, int>
{
public override string identifier { get { return "#BillableInvoiceCount"; } }
public override Func<IClientAccount, int> Calculation
{
get { return inputData => inputData.Invoices.Count(i => i.IsBillable); }
}
}
Each calculation is targeted at a specific type of object and returns different outputs depending on the nature of the calculation. For instance: Currency calculations may return decimals, counters would probably return integers or longs etc.
I have a calculation repository that loads itself up on application load and when there comes a time that a formula must be evaluated, the calculation engine takes the object that is being queried against - in this example, if we have some concrete instance of type IClientAccount and we wish to evaluate some formula against it - for instance, levy $1.20 for each invoice after the first 5: "Math.Max(#BillableInvoiceCount - 5, 0) * $1.20". The engine goes and grabs all calculations where TIn is of type IClientAccount and matches the calculation with the token found in the formula (i.e. #BillableInvoiceCount). Then some calculation engine such as NCalc, FLEE or another calculation engine would evaluate the final equation.
So, my problem is that I don't wish to iterate through every calculation looking for the correct token - and realistically, tokens could collide if they spanned multiple object types. For instance I may want to use the same token to mean different things in different contexts. It would be easier if I could narrow the calculations in my repository to just those where TIn matches the object type I'm trying to calculate against.
I have a few trains of thought at this point -
1). Can I create a repository that marshals only the TIn part of my object? I think the answer to this is likely, no... but on the chance of it being possible, I don't have the first clue how to implement this - does anyone have any ideas?
2). Is there a way to query my repository for all calculations where TIn matches the type of the object I'm querying against? If so, how?
3). Do I have multiple repositories based on all the combinations of TIn/TOut that I have calculations for... and if so, how do I go about marrying up the correct repositories with the object I'm querying against? Because I'm still trying to match up a repository based on only the TIn portion...
4). Make all my calculations return doubles instead of allowing them to return different types, then my repositories can be typed to just the input type making them simpler... but while this is simple, semantically, it just feels wrong.
Thoughts?
Cheers in advance :)
Remember that generics are a compile time artifact, you need to know at the time of writing what class you want if you want to use them. If you need run-time checking then the non-generic way is probably best.
Assuming you know you have the correct types your object -> object overload should work fine for your purposes. The .NET framework will throw an exception if the mapping fails so you don't have to worry about a silent failure there.
1). Can I create a repository that marshals only the TIn part of my object? I think the answer to this is likely, no... but on the chance of it being possible, I don't have the first clue how to implement this - does anyone have any ideas?
Marshalling refers to conversion of the underlying data, you can likely simply pass around raw objects in this case since your ICalculation.Calculate method does a conversion for you. The only problem you might have is if TIn is a value type and you pass in a null (in which case your Calculate null handling would not occur)
2). Is there a way to query my repository for all calculations where TIn matches the type of the object I'm querying against? If so, how?
I would try using the non-generic version, unless you want cleaner exception trees it should do the job in this case.
3). Do I have multiple repositories based on all the combinations of TIn/TOut that I have calculations for... and if so, how do I go about marrying up the correct repositories with the object I'm querying against? Because I'm still trying to match up a repository based on only the TIn portion...
If you wanted to do this the trick would be to have your saving method only save TIn rather than both. For example a Dictionary<Type,ICalculation> where the Type is TIn.
4). Make all my calculations return doubles instead of allowing them to return different types, then my repositories can be typed to just the input type making them simpler... but while this is simple, semantically, it just feels wrong.
One thing to be careful of here, my suggestions only work if you aren't doing any conversions between method calls. If you have an int in an object and you try to convert it to a double it will fail.
You could avoid this by calling Convert.ChangeType instead of doing a direct cast. It would work like so:
object ICalculation.Calculate(object inputData)
{
if (inputData == null && typeof(TIn).IsValueType)
return default(TOut);
return Calculate((TIn)Convert.ChangeType(inputData, typeof(TIn));
}
Note a couple of changes to the method:
I added an explicit null handler for value types, since Convert.ChangeType would just throw an exception.
I call the generic form of Calculate in case it was overloaded.
I made it non-virtual, unless you really have a good reason, you really shouldn't be overloading this method, since it just provides the symmetry of the two interfaces.
I don't convert the result. Both calculation and Calculate are guaranteed to return TOut so a conversion is redundant.
The addition of ChangeType which would allow you to silently handle passing an int into a decimal.
Note that there is a danger with ChangeType, it will be similar to an explicit cast. It will do its best to do the conversion no matter what happens to your data. It seems like overflows will be handled as expected, but truncations will happen silently.
The main point there is test your edge cases if you have any like that.
If you know everything derives from CalculationBase<,>, I suppose you could do:
// can also be made an extension method
static bool HasCorrectInType(ICalculation calc, Type desiredInType)
{
var t = calc.GetType();
do
{
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(CalculationBase<,>))
return t.GetGenericArguments()[0].IsAssignableFrom(desiredInType);
t = t.BaseType;
} while (t != null)
throw new Exception("The type " + calc.GetType() + " not supported");
}
Then use it like this:
List<ICalculation> repository = XXX;
var matches = repository.Where(c => HasCorrectInType(c, type));
Edit: New idea: If you put a new property:
public Type InType
{
get { return typeof(TIn); }
}
into your abstract class CalculationBase<TIn, TOut>, and also add this property to your non-generic interface ICalculation, then you won't have to iterate through the base classes, but can say calc.InType.IsAssignableFrom(desiredInType) directly.
I think the simplest solution should be picked. You can use reflection to get the specific type or just return double in all cases. If it is an intensive data processing, trying to find the specific type might slow it down, so returning a double or integer is totally fine.
Related
I know that there is a similar question here, but I would like to see an example, which clearly shows, what you can not do with interface and can with Type Class
For comparison I'll give you an example code:
class Eq a where
(==) :: a -> a -> Bool
instance Eq Integer where
x == y = x `integerEq` y
C# code:
interface Eq<T> { bool Equal(T elem); }
public class Integer : Eq<int>
{
public bool Equal(int elem)
{
return _elem == elem;
}
}
Correct my example, if not correctly understood
Typeclasses are resolved based on a type, while interface dispatch happens against an explicit receiver object. Type class arguments are implicitly provided to a function while objects in C# are provided explicitly. As an example, you could write the following Haskell function which uses the Read class:
readLine :: Read a => IO a
readLine = fmap read getLine
which you can then use as:
readLine :: IO Int
readLine :: IO Bool
and have the appropriate read instance provided by the compiler.
You could try to emulate the Read class in C# with an interface e.g.
public interface Read<T>
{
T Read(string s);
}
but then the implementation of ReadLine would need a parameter for the Read<T> 'instance' you want:
public static T ReadLine<T>(Read<T> r)
{
return r.Read(Console.ReadLine());
}
The Eq typeclass requires both arguments have the same type, whereas your Eq interface does not since the first argument is implicitly the type of the receiver. You could for example have:
public class String : Eq<int>
{
public bool Equal(int e) { return false; }
}
which you cannot represent using Eq. Interfaces hide the type of the receiver and hence the type of one of the arguments, which can cause problems. Imagine you have a typeclass and interface for an immutable heap datastructure:
class Heap h where
merge :: Ord a => h a -> h a -> h a
public interface Heap<T>
{
Heap<T> Merge(Heap<T> other);
}
Merging two binary heaps can be done in O(n) while merging two binomial heaps is possible in O(n log n) and for fibonacci heaps it's O(1). Implementors of the Heap interface do not know the real type of the other heap so is forced to either use a sub-optimal algorithm or use dynamic type checks to discover it. In contrast, types implementing the Heap typeclass do know the representation.
A C# interface defines a set of methods that must be implemented. A Haskell type class defines a set of methods that must be implemented (and possibly a set of default implementations for some of the methods). So there's a lot of similarities there.
(I guess an important difference is that in C#, an interface is a type, whereas Haskell regards types and type classes as strictly separate things.)
The key difference is that in C#, when you define a type (i.e., write a class), you define exactly what interfaces it implements, and this is frozen for all time. In Haskell, you can add new interfaces to an existing type at any time.
For example, if I write a new SerializeToXml interface in C#, I cannot then make double or String implement that interface. But in Haskell, I can define my new SerializeToXml type class, and then make all the standard, built-in types implement that interface (Bool, Double, Int...)
The other thing is how polymorphism works in Haskell. In an OO language, you dispatch on the type of the method the object is being invoked on. In Haskell, the type that the method is implemented for can appear anywhere in the type signature. Most particularly, read dispatches on the return type you want — something you usually can't do at all in OO languages, not even with function overloading.
Also, in C# it's kind of hard to say "these two arguments must have the same type". Then again, OO is predicated on the Liskov substitution principal; two classes that both descend from Customer should be interchangeable, so why would you want to constrain two Customer objects to both be the same type of customer?
Come to think of it, OO languages do method lookup at run-time, whereas Haskell does method lookup at compile-time. This isn't immediately obvious, but Haskell polymorphism actually works more like C++ templates than usual OO polymorphism. (But that's not especially to do with type classes, it's just how Haskell does polymorphism as such.)
Others have already provided excellent answers.
I only want to add a practical example about their differences. Suppose we want to model a "vector space" typeclass/interface, which contains the common operations of 2D, 3D, etc. vectors.
In Haskell:
class Vector a where
scale :: a -> Double -> a
add :: a -> a -> a
data Vec2D = V2 Double Double
instance Vector (Vec2D) where
scale s (V2 x y) = V2 (s*x) (s*y)
add (V2 x1 y1) (V2 x2 y2) = V2 (x1+x2) (y2+y2)
-- the same for Vec3D
In C#, we might try the following wrong approach (I hope I get the syntax right)
interface IVector {
IVector scale(double s);
IVector add(IVector v);
}
class Vec2D : IVector {
double x,y;
// constructor omitted
IVector scale(double s) {
return new Vec2D(s*x, s*y);
}
IVector add(IVector v) {
return new Vec2D(x+v.x, y+v.y);
}
}
We have two issues here.
First, scale returns only an IVector, a supertype of the actual Vec2D. This is bad, because scaling does not preserve the type information.
Second, add is ill-typed! We can't use v.x since v is an arbitrary IVector which might not have the x field.
Indeed, the interface itself is wrong: the add method promises that any vector must be summable with any other vector, so we must be able to sum 2D and 3D vectors, which is nonsense.
The usual solution is to switch to F-bounded quantification AKA CRTP or whatever it's being called these days:
interface IVector<T> {
T scale(double s);
T add(T v);
}
class Vec2D : IVector<Vec2D> {
double x,y;
// constructor omitted
Vec2D scale(double s) {
return new Vec2D(s*x, s*y);
}
Vec2D add(Vec2D v) {
return new Vec2D(x+v.x, y+v.y);
}
}
The first time a programmer meets this, they are usually puzzled by the seemingly "recursive" line Vec2D : IVector<Vec2D>. I surely was :) Then we get used to this and accept it as an idiomatic solution.
Type classes arguably have a nicer solution here.
After a long study of this issue, I came to an easy method of explaining. At least for me it's clear.
Imagine we have method with signature like this
public static T[] Sort(T[] array, IComparator<T> comparator)
{
...
}
And implementation of IComparator:
public class IntegerComparator : IComparator<int> { }
Then we can write code like this:
var sortedIntegers = Sort(integers, new IntegerComparator());
We can improve this code, first we create Dictionary<Type, IComparator> and fill it:
var comparators = new Dictionary<Type, IComparator>()
{
[typeof(int)] = new IntegerComparator(),
[typeof(string)] = new StringComparator()
}
Redesigned IComparator interface so that we could write like above
public interface IComparator {}
public interface IComparator<T> : IComparator {}
And after this let's redesign Sort method signature
public class SortController
{
public T[] Sort(T[] array, [Injectable]IComparator<T> comparator = null)
{
...
}
}
As you understand we are going to inject IComparator<T>, and write code like this:
new SortController().Sort<int>(integers, (IComparator<int>)_somparators[typeof(int)])
As you already guessed this code will not work for other types until we outline the implementation and add in Dictionary<Type, IComparator>
Notice, the exception we will see only on runtime
And now imagine if this work was done for us by the compiler during build and it threw exception if it could not find the comparator with corresponding types.
For this, we could help the compiler and add a new keyword instead of usage attribute. Out Sort method will be look like this:
public static T[] Sort(T[] array, implicit IComparator<T> comparator)
{
...
}
And code of realization concrete Comparator:
public class IntegerComparator : IComparator<int> implicit { }
Note, we use the keyword 'implicit', after this compiler will be able to do
routine work, which we wrote above, and the exception will be thrown during
compile-time
var sortedIntegers = Sort(integers);
// this gives us compile-time error
// because we don't have implementation of IComparator<string>
var sortedStrings = Sort(strings);
And give the name to this style of implementation Type Class
public class IntegerComparator : IComparator<int> implicit { }
I hope that I understood correctly and understandably explained.
PS: The code does not pretend to work.
Background
I'm starting work on a little OSS library called Sieve.NET.
The signature lets someone define a Sieve as follows:
new EqualitySieve<ABusinessObject>().ForProperty(x => x.AnInt);
This actually returns a Sieve<ABusinessObject, int>, but I've done my best to ensure that users don't have to care about that part too too much.
The Task
I would like to find a way to put an interface on this, where I don't care about the property type at all -- only that it is consistent throughout.
So essentially, I would like to be able to declare an ISieve<TFilterObjectType>, and by able to have that Interface define something like:
ISieve<TFilterObjectType, TTypeIDontCareAbout> ForValue(TTypeIDontCareAbout);
My goal is to be able to have a class composed from ISieve<ABusinessObject> and not ISieve<ABusinessObject, int>.
Question
Is there a way for an interface to declare a type that effectively is a wildcard, and says "I don't care what type this is, only that it's consistent?"
My initial research says no but I'm hoping to be proven wrong.
Updates & Clarifications
What I'm really trying to figure out is:
I allow users to create an EqualitySieve<ABusinessObject>().ForProperty(x=>x.AnInt).
This actually returns an EqualitySieve<ABusinessObject, int> to the user, but since it's a fluent interface I remove them from having to care about that part.
I would like EqualitySieve, LessThanSieve, etc. to implement ISieve<ABusinessObject>.
I would like ISieve<ABusinessObject to enforce a contract whereby I could allow someone to call ForValues() and expect it to return an ISieve with the updated values.
However, at that point, the EqualitySieve<ABusinessObject> is actually an EqualitySieve<ABusinessObject, int>. But I don't particularly care about the property type at that point.
Essentially, since I'm abstracting the away the EqualitySieve<ABusinessObject, int> portion, I also wanted to see if I could abstract that away when referring to objects via the interface.
The long-term plan is that I want to have a SieveLocator, where classes can implement an IFindableSieve<ABusinessObject> that ideally would return an ISieve<ABusinessObject>. Then my goal would be to be able to find those Sieves for a given object.
So I'm thinking this is likely a limitation of my design and I'll have to find some other way around it. Any suggestions on that or references to a pattern I might not be seeing would be helpful as well.
You can place generic type parameters on both the interface and the interface's methods. So the following example would define a generic interface where the F method takes one of these "I don't care what type this is, only that it's consistent" parameters.
interface I<T>
{
//The generic type parameter U is independent of T.
//Notice how F "forwards" the type U from input to output.
Tuple<T, U> F<U>(U u);
}
Consider the following toy class:
class C : I<char>
{
public char Value { get; set; }
public Tuple<char, U> F<U>(U u)
{
return Tuple.Create(Value, u);
}
}
Here's some example usage:
I<char> instance = new C { Value = '!' };
Tuple<char, int> x = instance.F(5); // ('!', 5)
Tuple<char, string> y = instance.F("apple"); // ('!', "apple")
Updates
I allow users to create an EqualitySieve<ABusinessObject>().ForProperty(x=>x.AnInt).
This actually returns an EqualitySieve<ABusinessObject, int> to the user, but since it's a fluent interface I remove them from having to care about that part.
I would like EqualitySieve, LessThanSieve, etc. to implement ISieve<ABusinessObject>.
Using the ideas I mentioned above, you can do what (I think) you want.
interface ISieve<T>
{
//It's still not clear what you actually want in this interface...
}
static class Sieve
{
public EqualitySieve<T> Equality<T>()
{
return new EqualitySieve<T>();
}
public LessThanSieve<T> LessThan<T>()
{
...
}
}
class EqualitySieve<T> : ISieve<T>
{
//Notice how the property type P is independent of T
//and can be inferred here from the passed expression
public EqualitySieve<T, P> ForProperty<P>(
Expression<Func<T, P>> propertyExpression)
{
return new EqualitySieve<T, P>
{
PropertyExpression = propertyExpression
};
}
}
class EqualitySieve<T, P> : ISieve<T>
{
public Expression<Func<T, P>> PropertyExpression { get; set; }
}
Usage:
//Assuming MyObject.MyProperty is an int property
//s has type EqualitySieve<MyObject, int>
var s = Sieve.Equality<MyObject>().ForProperty(x => x.MyProperty);
There may be some tricks so callers don't need to specify a type on a generic method (think how LINQ works), but unfortunately your research was correct, there is no way to infer a type while composing a class that uses that type.
The closest you can get to it is having two layers of interfaces where the outer layer does not use any of the functions that rely on the TTypeIDontCareAbout type.
interface ISieve<TFilterObjectType,TTypeIDontCareAbout> : ISieve<TFilterObjectType>
{
TFilterObjectType ForValue(TTypeIDontCareAbout forValue);
}
interface ISieve<TFilterObjectType>
{
TFilterObjectType SomeOtherFunction();
}
I don't know how to solve all your problems but I think Timothy's approach is what you want to go for the two points
I allow users to create an EqualitySieve<ABusinessObject>().ForProperty(x=>x.AnInt).
This actually returns an EqualitySieve<ABusinessObject, int> to the user, but since it's a fluent interface I remove them from having to care about that part.
interface ISieve<TFilterObjectType>
{
TFilterObjectType SomeOtherFunction();
EqualitySieve<TFilterObjectType, T> ForProperty<T>(Func<TFilterObjectType, T> selector);
EqualitySieve<TFilterObjectType, T> ForProperty<T>(Expression<Func<TFilterObjectType, T>> selector); //This is how you would do it if you wanted IQueryable support.
}
I have a definition like this:
public static IQueryable<D> ReturnDTO<E, D>(this IQueryable<E> query)
where D : BaseDTO, new()
where E : BaseObjectWithDTO<D, int>
{
//expression tree code to convert
}
BaseObjectWithDTO defines what type it's DTOs are. Hence I would have thought the by defining E I would have been also defining D.
But IQueryable.ReturnDTO() requires that the generic parameters be specified like this:
IQueryable.ReturnDTO<someEntity, someDTO>();
Which is obviously UGLY.
I tried making this IQueryable<E> as this IQueryable<BaseObjectWithDTO<D, int>> instead but then this has nothing as the in of the func because it won't take a type inferred by the Generic Parameter of the IQuerayble:
var projection = Expression.Lambda<Func<E, D>>(memberInitExpression, itemParam);
Ideas on how to get this to not require the types be passed every time?
Unfortunately, C#'s generic type inference system isn't as powerful as it could be. If you include a parameter involving D, then it can infer it. For example...
public static IQueryable<D> ReturnDTO<E, D>(this IQueryable<E> query,
IQueryable<BaseObjectWithDTO<D, int>> dummy)
// now you can do...
myQueryable.ReturnDTO(myQueryable);
// instead of
myQueryable.ReturnDTO<BaseObjectWithDTO<BaseDTO, int>, BaseDTO>();
It's confusing and arguably a poor design to pass the same variable in twice, but it's better (IMHO) than having to explicitly specify the types or resort to reflection or other runtime techniques to extract the types (when that's otherwise unnecessary).
Since you aren't actually going to use the dummy parameter, it doesn't matter what the value is, as long as the type is right, so you might still be able to use this at the end of a query chain, e.g. this will still return the expected value, even though you pass in two different IQueryables.
var result = otherQueryable.Where(...).ReturnDTO(otherQueryable);
If you prefer to be slightly less cryptic, you could make the dummy parameter D dummy, and then e.g. myQueryable.ReturnDTO(default(SomeDTO)) (here using default as a clear way of getting a null or default value without having a reference to a variable/field/property of that type) if you prefer.
I don't think it is possible as you currently have it designed, this MSDN page states that type inference is not possible in this scenario:
The same rules for type inference apply to static methods and instance
methods. The compiler can infer the type parameters based on the
method arguments you pass in; it cannot infer the type parameters only
from a constraint or return value.
That means you have to pass in a parameter of your type to this method for the compiler to be able to infer the types.
You have to specify the type, but it doesn't have to be done explicitly in the q.Return<E,D>(). There are ways that you can pass specify the type parameter so that it can be inferred implicitly. To do that, you'll need to change the signature a bit.
public static IQueryable<D> ReturnDTO<E, D>(this IQueryable<E> query, D dtoTypeExample = default(D))
where D : BaseDTO, new()
where E : BaseObjectWithDTO<D, int>
{
//expression tree code to convert
}
Now, even though there's a default parameter, the compiler won't be able to get it unless you pass some argument in. The thing you pass in doesn't have to be used by the method in any other way though. For example, assume you have:
public class ProductDTO : BaseDTO {
public static ProductDTO Empty { get { return new ProductDTO(); } }
}
public class Product : BaseObjectWithDTO<ProductDTO,int> {
public static IQueryable<Product> QuerySource { get; set; }
}
You could then call:
ProductDTO dto = Product.QuerySource.ReturnDTO(ProductDTO.Empty);
I'm not saying that this is necessarily a good idea, but you could do it. Also, it doesn't have to be the actual type that you pass in - you just need to pass in something that's close enough for the compiler to infer the intended type. For example, you could have a signature like:
public static IQueryable<D> ReturnDTO<E, D>(this IQueryable<E> query, Func<D,D> dtoIdentity = default(Func<D,D>))
where D : BaseDTO, new()
where E : BaseObjectWithDTO<D, int>
{
//expression tree code to convert
}
then if you have:
public class ProductDTO : BaseDTO {
public static ProductDTO Identity(ProductDTO dto){ return dto; };
}
public class Product : BaseObjectWithDTO<ProductDTO,int> {
public static IQueryable<Product> QuerySource { get; set; }
}
You could then call:
ProductDTO dto = Product.QuerySource.ReturnDTO(ProductDTO.Identity);
This might make more semantic sense to some, but it's somewhat subjective. Once again, I'm not recommending this, just saying that you can do it. If you do decide to do it though, it might save you a little work to have a self-referential generic base (Warning: Eric Lippert discourages this kind of thing). But anyway, your design would then look like:
public abstract class BaseDTO<T> where T : BaseDTO<T>, new()
{
public static T Empty { get { return new T(); } }
}
public class ProductDTO : BaseDTO<ProductDTO> { }
You could also add the type constraint to your ReturnDTO method if you want to enforce an invariant that all DTOs were then self-referential derivatives of BaseDTO<T> with public parameterless constructors. But, if you're trying to write what would conventionally be considered good code you probably won't do any of this and you'll just close your eyes and explicitly use the parameter constraint if you think it's ugly.
There is one other thing I thought of, which wouldn't be so frowned upon. Think about the Queryable.Cast<T> and Queryable.OfType<T> methods. They take a non generic IQueryable parameter but returns an IQueryable<T>. If you make sure to validate your assumptions about the parameter, it's probably clean enough. Then you would lose some compile-time type-safety though. You would need to have a non-generic base like BaseObjectWithDTO that BaseObjectWithDTO<TData,TKey> would inherit from. Your method would then look like:
public static IQueryable<D> ReturnDTO<D>(this IQueryable<BaseObjectWithDTO> query)
where D : BaseDTO, new()
{
if(query == null) throw new ArgumentNullException("query");
if( !typeof(BaseObjectWithDTO<D,int>) .IsAssignableFrom(query.GetType().GetGenericParameters()[0]))
throw new ArgumentOutOfRangeException("query");
//expression tree code to convert
}
That's not terrible. But it might not be good either. It's probably better than the other options I listed, but who knows.
Another syntax that might work for you just occurred to me, but it's also pretty abusive. Imagine you did go the BaseDTO<T> where T : BaseDTO<T>,new() route. You could declare the method on that type to extract the DTO queryable. This is what I'm thinking:
public abstract class BaseDTO<T>
where T : BaseDTO<T>, new()
{
public static T From(BaseObjectWithDTO<T,int> entity){
if(entity == null) throw new ArgumentNullException("entity");
//expression tree code to convert
}
}
then you don't really need that method ReturnDTO as an extension method anymore, because you have normal LINQ. You could still add it as syntactic sugar if you want, but using these semantics instead, your call ends up looking like:
IQueryable<ProductDTO> dtoQuery = from entity in Product.QuerySource select ProductDTO.From(entity);
which can also be written as
Product.QuerySource.Select(entity => ProductDTO.From(entity));
and if you were using an IEnumerable instead of an IQueryable could be
Product.QuerySource.Select(ProductDTO.From);
Please remember: All I'm saying is that you can do things this way. I'm not saying you should.
I am writing a Silverlight and WCF project.
I have used the Entity Framework in Silverlight to get the data from the database, I have multiple pages where I use EF.
Now, I have more than 100 types of entity class and hence multiple known list types.
In my WCF interface I want to create one generic function where I can accept all this list types as one generic parameter.
So my WCF function should be like
public string TestBadal(List<Object> list)
{
return "test";
}
My question here is, how can I cast all the known lists to List. I am fairly new to this so any help will be much appreciated.
Thank you.
you can use T
public static List<T> o<T>(List<T> a)
{
return a = new List<T>();
}
As Sophex states you can write a generic function to process a List<> or better still an IList<> of anything.
So your example would become,
public string TestBadal<T>(IList<T> list)
{
return "test";
}
This is very generic and requires and implies little about T. This may be sufficient for the processing you want to perform but, you don't say.
In general, you should view your method signature as a promise that the caller has to make to the function. You should limit the promise to only what is required for your function to do its job. This way, the promise is easier to make and your function can get reused more with less commitment from the caller.
Your function as it stands, doesen't actually need a parameters and would be better defined as a string const but say, all you wanted to do was enumerate the items you could use,
public string TestBadal<T>(IEnumerable<T> entities)
{
foreach(T entity in entities)
{
...
}
}
If your processing is especially related to the EF nature of the data source you could do,
public string TestBadal<TEntity>(EntitySet<TEntity> entities)
where TEntity : class
{
...
}
If you need to know somthing about the type in the list then you have two sensible options.
Either you require the types to implement a certain interface, this essentialy makes your function non-generic and could be awkward with in conjunction with EF.
public string TestBadal(IEnumerable<IDefinedType> definedTypeInstances)
{
foreach(IDefinedType instance in definedTypeInstances)
{
var x = instance.SomeDefinedProperty;
}
}
Or, you can take the non generic parts of the function as a typed delegate parameter, keeping the function generic, possibly somthing like this.
public string TestBadal<T>(
IList<T> list,
Func<T, string> stringSelector)
{
var result = new StringBuilder();
for(var i = 0; i < list.Count; i++)
{
result.AppendLine(stringSelector(list[i])
}
return result.ToString();
}
You could call this function with a lambda expression somthing like this,
var result = TestBadal(entities, e => e.SomeStringProperty);
I hope this answer both gives you some ideas and illustrates my point that the right answer depends on what you want your function to achieve.
Is it possible to constrain a generic method on specific types?
I want to write something like this:
public T GetValue<T>(string _attributeValue) where T : float, string
{
return default(T); // do some other stuff in reality
}
I'm mostly just trying to avoid having a giant switch statement inside the method or having to throw an exception if an invalid type is specified.
Edit: Ack. I knew string is not a value type. I started out with two numeric types earlier. Sorry.
You can't use generic constraints to express the limitations you are interested in. Generics are not meant to express variation based on disjoint types - they're meant to express variation that is unified over a hierarchy of types (or those implementing certain interfaces).
You have a few alternative choices, however. Which you choose depends on the exact nature of what you're trying to do.
Use differently named methods to express each operation. I tend to use this approach when each method is truly doing something different. You could argue that returning a different type of value from a method is essentially a different operation, and deserves its own unique name.
float GetFloat(string attrName) { }
string GetString(string attrName) { }
Provide a "default value" to allow the type to be inferred. In many designs where you ask for a value by name it useful to supply a default value. This can allow you to employ overloading to differentiate between which method to invoke (based on the type of the default value). Unfortunately, this approach is quite fragile - and breaks easily when passing literal values to overloads that accept numeric primitives (int vs. uint vs. long).
float GetValue(string attrName, float defaultValue) { ... }
string GetValue(string attrName, string defaultValue) { ... }
Use a generic method, but throw a runtime exception if the type isn't one of those you support. Personally I find this kind of ugly and in violation of the spirit of generics - generics should unify functionality over a hierarchy or a set of types implementing some interface. However, in some cases it makes sense to do so (if let's so one specific type cannot be supported, let's say). Another problem with this approach is that the signature of the generic method cannot be inferred from any parameters, so you would have to specify the type desired when calling it ... at which point it's not much better (from a syntax point of view) than having different method names.
T GetValue<T>( string attrName )
{
if( typeof(T) != typeof(string) ||
typeof(T) != typeof(float) )
throw new NotSupportedException();
return default(T);
}
// call it by specifying the type expected...
float f = GetValue<float>(attrName);
string s = GetValue<string>(attrName);
Use an out parameter instead of a return value. This approach works well, but it loses the concise syntax of being able to call a method and act on a return value, since you first have to declare a variable to populate.
void GetValue( string attrName, out float value )
void GetValue( string attrName, out string value )
// example of usage:
float f;
GetValue( attrName, out f );
string s;
GetValue( attrName, out s );
This is not possible to do with compile time support. You can do this check in the static constructor and throw an exception (in the case the T is defined on the type) or (in your case) in the method body itself, but in that case it would be a runtime validation.
No, you can not specify a range of types. If you want all primatives you can do (and i know string is not included)
where T: struct
No, it's not possible.
And string is a reference type, not a value type.
The closest you can get is constraining on all value types (minus Nullable types):
public T GetValue<T>(string _attributeValue) where T : struct
Depending on what you're actually doing inside the method, there may be various ways to achieve your goal (other than switch/case). Consider changing your example to be a little more meaningful...
One other option might also be to make your method private and provide public wrappers that are specific:
private T GetValue<T>(string _attributeValue) where T : struct
{
return default(T);
}
public float GetFloatValue(string _attributeValue)
{
return GetValue<float>(_attributeValue);
}
public int GetIntValue(string _attributeValue)
{
return GetValue<int>(_attributeValue);
}
That would allow you to constrain the public members of your class to the desired types but still use generic code internally so you don't have to repeat yourself.