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.
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>
.
My initial research says no but I'm hoping to be proven wrong.
What I'm really trying to figure out is:
EqualitySieve<ABusinessObject>().ForProperty(x=>x.AnInt)
.EqualitySieve<ABusinessObject, int>
to the user, but since it's a fluent interface I remove them from having to care about that part. EqualitySieve
, LessThanSieve
, etc. to implement ISieve<ABusinessObject>
. 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.EqualitySieve<ABusinessObject>
is actually an EqualitySieve<ABusinessObject, int>
. But I don't particularly care about the property type at that point.EqualitySieve<ABusinessObject, int>
portion, I also wanted to see if I could abstract that away when referring to objects via the interface.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.Whenever you want to restrict the type parameter to subtypes of a particular class you can use the bounded type parameter. If you just specify a type (class) as bounded parameter, only sub types of that particular class are accepted by the current generic class.
Similar to John Carpenter's answer, you can override the generic method with the same generic method, but simply use the as operator to check and cast it to the desired type. This has the added benefit of using null-testing to check if the conversion worked.
Yes, you can define a generic method in a non-generic class in Java.
An attribute cannot inherit from a generic class, nor can a generic class inherit from an attribute.
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")
- 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 implementISieve<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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With