Ninject: Binding an interface with a generic that is also an interface - c#-4.0

I have searched this issue but with no luck. Here we go.
Suppose I have an interface:
interface IQueryRepository<T> where T : class
and I want to bind any requests for:
IQueryRepository<IClient>
to:
ConcreteQueryRepository<Client>
I've tried the obvious:
Bind<IGenericQueryRepository<IClient>>().To<ConcreteQueryRepository<Client>>()
But I get an error:
ConcreteQueryRepository<Client> cannot be used as type parameter 'TImplementation' in
the generic type or method 'Ninject.Syntax.IBindingToSyntax<T>.To<TImplementation>()'
There is no implicit reference conversion from 'ConcreteQueryRepository<Client>'
to 'IGenericQueryRepository<IClient>'
But I don't understand why since GenericQueryRepository implements IGenericQueryRepository and Client implements IClient.
I would like Ninject to give me a concrete generic repository where T is Client. I want this to avoid using concrete types in the code.
Can it be done?

This has to do with Covariance and Contravariance.
In your question you mentioned the following:
... GenericQueryRepository implements IGenericQueryRepository and Client implements IClient.
Let's make it simpler by using fruits: Fruit implements IFruit. We'll also create a Tree class.
public interface IFruit { }
public class Fruit : IFruit { }
public class Tree<T> where T : IFruit { }
Tree<IFruit> tree = new Tree<Fruit>() // error
This will reproduce the same kind of error you're experiencing. Why? Simple.
Though Fruit implements IFruit, an Fruit Tree doesn't implement a IFruit Tree. There is no cast possible between the Fruit Tree and the IFruit Tree, although you would expect it. They are both Trees, but with a different type parameter. The fact that their type parameters are related to each other, doesn't matter.
In other words: there is no cast possible between the Fruit Tree and the IFruit Tree, because their type parameters don't match.
In general, when casting with generics, make sure their type parameters match. However, there are a few exceptional cases. See Variance in Generic Interfaces.
In your case, you could fix it by using IClient as type parameter for the GenericQueryRepository class. Doing this will allow casting because the type parameters match. But I don't know your application architecture, so this fix might be inapplicable in your case.
EDIT: To make it easier to understand, copy paste the code below and see what the compiler says.
interface IFruit { }
class Fruit : IFruit { }
interface ITree<T> where T : IFruit { }
class Tree<T> : ITree<T> where T : IFruit { }
class Program
{
static void Main(string[] args)
{
ITree<Fruit> test1 = new Tree<Fruit>(); // compiles: type parameters match
ITree<IFruit> test2 = new Tree<Fruit>(); // fails: type parameters don't match
ITree<Fruit> test3 = new Tree<IFruit>(); // fails: type parameters don't match
ITree<IFruit> test4 = new Tree<IFruit>(); // compiles: type parameters match
IEnumerable<IFruit> test5 = new List<Fruit>(); // compiles: this is one of the exceptional cases
}
}
That should clear things up about what is and what is not possible.

I've had the same problem when trying to bind a Dapper query to an interface type, thinking about it, it seems to make sense that Dapper can't instantiate an Interface type.
The interface is only a contract and does not know about how to instantiate a concrete implementation of it.
Dapper needs a type that is concrete implementation of the interface type otherwise Dapper would also have to know which concrete implementation of the interface to instantiate, and in that case Dapper would behave like a DI container which, indeed, it isn't.

Related

Is there a substitute for enum in kotlin Android besides enumerated annotation?

So after I created lots of enum classes in android (Kotlin), I learnt that enums are not very space efficient in android. So I tried to find another way of doing it. I found the enumerated annotation - #StringDef. However, Kotlin doesn't seem to support this well and there are no warning or error messages even if I pass something unexpected to a method.
So to clarify what I want to do: I have tons of constant strings that can be classified to different groups (I listed them in different enum class), and when calling some setter functions, I want the caller to choose only from the specific group of things that can be chosen.
For example:
enum class Cat (val breed: String){
AMER_SHORTHAIR("American Shorthair"),
SIAMESE("Siamese");
}
enum class Dog (val breed: String){
GOLDEN_R("Golden Retriever"),
POODLE("Poodle");
}
fun adopt(cat: Cat, dog: Dog){
print("I adopted a "+cat.breed+" and a "+dog.breed)
}
In this case, I can only choose from cats for the first param, and dogs for the second. Is there a way of doing this kind of type-safe methods without using enums?
To avoid using enums, I might need to change the above functionality to:
const val AMER_SHORTHAIR = "American Shorthair"
const val SIAMESE = "Siamese"
const val GOLDEN_R = "Golden Retriever"
const val POODLE = "Poodle"
fun adopt(cat: String, dog: String){...}
This is not ideal since we can get all kinds of typos which happens in our current implementation and is why I switched to enum in the first place. But overall, space consumption > type safe. So if there is no better way, I will need to switch back.
Please let me know if there is any efficient ways to achieve. I've thought about using maps or lists, but indexing or accessing the strings become cumbersome because I need to map the string to themselves (no hard coded strings here except for the first assignment like AMER_SHORTHAIR = "American Shorthair").
Thanks.
I agree with #EpicPandaForce comment: you should not optimize Enums in this way.
That said, there will be a new feature: Inline Classes coming in Kotlin 1.3 (https://blog.jetbrains.com/kotlin/2018/07/see-whats-coming-in-kotlin-1-3-m1/).
With this new feature you could do the following:
inline data class Cat(private val breed: String)
inline data class Dog(private val breed: String)
val AMER_SHORTHAIR = Cat("American Shorthair");
val SIAMESE = Cat("Siamese");
val GOLDEN_R = Dog("Golden Retriever");
val POODLE = Dog("Poodle");
fun adopt(cat: Cat, dog: Dog){
print("I adopted a "+cat.breed+" and a "+dog.breed)
}
Whenever you use this values the compiler inlines to raw strings.
In contrast to type aliases, the compiler is able to check the origin types for inline classes.
I like to use Sealed class instead of Enums; It provides some extra goodies over the normal class; More on this here
Something like this;
class LoggingBehaviour #JvmOverloads constructor(private val logLevel: LogLevel = Debug) {
fun log(tag: String, message: String) {
when (logLevel) {
is Error -> Log.e(tag, message)
is Warn -> Log.w(tag, message)
is Info -> Log.i(tag, message)
is Debug -> Log.d(tag, message)
is Verbose -> Log.v(tag, message)
}
}
}
sealed class LogLevel
object Error : LogLevel()
object Warn : LogLevel()
object Info : LogLevel()
object Debug : LogLevel()
object Verbose : LogLevel()
Also annotations like IntDef and StringDef can be used. More of it here

Groovy DSL given syntax validation

Actually I'm experimenting writing a DSL with groovy. So far ...
There are some things unclear to be regarding delegation and intercepting unwanted (Closure) structures:
first of all: How can I throw a (type of?) Exception to point to the correct line of code in the DSL that fails?
assuming
abstract MyScript extends Script {
def type(#DelegateTo(MyType) Closure cl) {
cl.delegate = new MyType()
cl()
this
}
}
under
new GroovyShell(this.class.classLoader, new CompilerConfiguration(scriptBaseClass: MyScript.name)).evaluate(…)
the passed DSL / closure
type {
foo: "bar"
}
passes silently.
I'm aware of, that foo: is just a POJ label but I'm not that sure what that defined Closure is interpreted as?
Neither did I found anything regarding the AST metaprogramming to get in touch of any defined labels to use them?
giving in
type {
foo = "bar"
}
it's clear that he will try to set the property foo, but do I really have to intercept unwanted fields/props by
class MyType {
def propertyMissing(String name) {
… // where I'm unable to println name since this leads to field access 'name' ...
}
}
while user is still allowed to pass
type {
foo "bar"
}
which leads to method not defined .. so I have to write additionally some metaClass.methodMissing or metaClass.invokeMethod stuff ..
meanwhile I tend to dismiss any closures in my dsl only working with simple
def type(Map vars) {
store << new MyType(vars)
// where in the constructor I was forced to write metaClass stuff to validate that only fields are given in the map that are defined in the class
}
that works, but both drafts are not what I expected to do when reading "groovy is so great for making DSLs" ...
I would experiment with the different options and then settle for one.
To guide your users you should give feedback similar to that of the regular compiler (i.e. line-number and column, maybe the expression).
Enforcing the correctness of the input can be non-trivial -- depending on your DSL.
For example:
type {
foo: "bar"
}
Is just a closure that returns the String bar. Is that something your user is supposed to do? The label will be part of the AST, AFAIK in org.codehaus.groovy.ast.stmt.Statement.statementLabels. If you want this syntax to assign something to foo then you'll need to rewrite the AST. The Expression could become a Declaration for the local Variable foo or could become an assignment for the Field foo. That's really up to you, however, Groovy gives you some capabilities that make creating a DSL easier:
You already used #DelegateTo(MyType) so you could just add a Field foo to MyType:
class MyType {
String foo
}
And then either use #CompileStatic or #TypeChecked to verify your script. Note that #CompileStatic will deactivate Run-time Metaprogramming (i.e. propertyMissing etc. won't be called anymore.) while #TypeChecked does not. This, however, will only verify Type-Correctness. That is: assigning to anything but a declared Field will fail and assigning an incompatible Type will fail. It does not verify that something has been assigned to foo at all. If this is required you can verify the contents of the delegate after calling the Closure.

Optional arguments on interface and class can conflict

I have just come across an interesting gotcha where optional arguments on an interface and the implementing class can conflict.
I found this out the hard way (school boy error) whilst experimenting. You cannot spot it in the debugger and I assumed it was me messing up the dependency injection.
I'm guessing this is so an alternative interface can give a differing view on what default behaviour should be?
Is there a compiler warning or style cop rule to help point this out?
public interface MyInterface
{
MyStuff Get(bool eagerLoad = true); //this overrules the implementation.
}
public class MyClass : MyInterface
{
public MyStuff Get(bool eagerLoad = false) //will still be true
{
//stuff
}
}
Remember default arguments are a compile-time feature. The compiler picks up the default argument based on the static type of the reference in question and inserts the appropriate default argument. I.e. if you reference is of the interface type you get one behavior but if the reference is of the class type you get the other in your case.

class properties are not available in generic method c#

I am calling a generic method with two different classes as below:
FillDataPointsInOrder<Metrics>(dataPoints.Where(O => O.SortOrder != null).OrderBy(O => O.SortOrder));
FillDataPointsInOrder<Metric>(angieStatsCmp.GetDataColumns());
private void FillDataPointsInOrder<T>(IEnumerable<T> dataPoints)
{
foreach (T dpoint in dataPoints)
{
if (!dpoint.IsPhone)
FillDrp(this.EmailDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
if (dpoint.IsPhone && this.IsPhoneShop)
FillDrp(this.PhoneDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
}
}
in "FillDataPointsInOrder" method I am getting compile errors :
'T' does not contain a definition for 'IsPhone' and no extension method 'IsPhone' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Same errors for Name , MetricId and VName properties.
Not sure why T is not able to access properties of Metrics and Metric.
If I remove the code from generic method and write it directly in foreach over dataPoints it is working fine.
Can somebody advise what is wrong here?
FillDataPointsInOrder only knows it will be called with a T. T could actually be string, int or anything.
If you want to call properties on T, you will have to use a where constraint.
But in this case it looks like your method does not even need to be generic.
If both Metric and Metrics share a base class or an interface that has the properties you need:
interface IMetric {
bool IsPhone {get; }
}
you could just have:
private void FillDataPointsInOrder(IEnumerable<IMetric> dataPoints)
Note that IEnumerable is covariant, so if Metric is a IMetric, IENumerable<Metric> is a IEnumerable<IMetric>
You need to at least tell the compiler something about T if you want to do that. Do you have an interface that has members like IsPhone, Name, MetricId, etc. that your classes implement?
If so you can add a 'where' constraint to your class definition:
public class Something<T> where T : ISomethingElse
...where ISomethingElse is the interface that implements IsPhone.

XmlSerializer, XmlArray with dynamic content... how?

To start: This is also for REST deserialiaztion, so a custom XmlSerializer is out of the question.
I have a hjierarchy of classes that need to be serializable and deserializable from an "Envelope". It has an arrayelement named "Items" that can contain subclasses of the abstract "Item".
[XmlArray("Items")]
public Item [] Items { get; set; }
Now I need to add XmlArrayItem, but the number is not "fixed". We use so far reflection to find all subclasses with a KnownTypeProvider so it is easy to extend the assembly with new subtypes. I dont really want to hardcode all items here.
The class is defined accordingly:
[XmlRoot]
[KnownType("GetKnownTypes")]
public class Envelope {
but it does not help.
Changing Items to:
[XmlArray("Items")]
[XmlArrayItem(typeof(Item))]
public Item [] Items { get; set; }
results in:
{"The type
xxx.Adjustment
was not expected. Use the XmlInclude
or SoapInclude attribute to specify
types that are not known statically."}
when tyrying to serialize.
Anyone an idea how I can use XmlInclude to point to a known type provider?
The KnownTypesAttribute does not work for XmlSerializer. It's only used by a DataContractSerializer. I'm quite sure that you can exchange the serializer in WCF, because I have done that for the DataContractSerializer. But if that's not an option, you have to implement IXmlSerializable yourself and handle type lookup there.
Before disqualifying this solution: You just have to implement IXmlSerializable just for a special class which replaces Item[]. Everything else can be handled by the default serializer.
According to: http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/thread/83181d16-a048-44e5-b675-a0e8ef82f5b7/
you can use different XmlSerializer constructor:
new XmlSerializer(typeof(Base), new Type[] { typeof(Derived1), ..});
Instead of enumerating all derived classes in the base definition like this:
[System.Xml.Serialization.XmlInclude(typeof(Derived1))]
[System.Xml.Serialization.XmlInclude(typeof(Derived2))]
[System.Xml.Serialization.XmlInclude(typeof(DerivedN))]
I think you should be able to use your KnownTypeProvider to fill the array in the XmlSerializer's constructor.

Resources