Apply rules Generically on top of generics - c#

I'm trying to make an mock data generator which will generate mocks based on a set of rules. I've been playing around with Bogus. I don't want to have to setup my rules for my entity classes each time, I would like to generically be able to apply rules to classes if they derrive from some interface.
Imagine I have entities which reuse a generic interface:
public interface IHasGeneric<T>
where T : IHasGeneric<T>
{
string Marker { get; set; }
}
public class Foo : IHasGeneric<Foo>
{
public string Marker { get; set; }
}
public class Bar : IHasGeneric<Bar>
{
public string Marker { get; set; }
}
Note: I'm aware this doesn't depict why I have a generic which takes in itself as a parameter. However, it takes too much to explain and cannot be changed from my architecture. So please work with it as a requirement.
Now I want to create a centralized Factory For Fakers, However I'm struggling to figure out how I can apply the rules generically to any type that is going to be generated.
public class MockDataGenerator
{
public T Generate<T>()
where T : class
{
var faker = new StatefulFaker<T>();
this.ApplyDefaultRules<T>(faker);
}
public void ApplyDefaultRules<T>(StatefulFaker<T> faker)
where T : class
{
//T Cannot be used as a type parameter 'T' ... No Implicit Conversion to IHasGeneric<T>
if (typeof(T) is IHasGeneric<T>>)
{
}
}
}
When trying to cast T to see if rules can be applied I get an error
T Cannot be used as a type parameter 'T' ... No Implicit Conversion to IHasGeneric. How can I generically apply rules to types which implement an interface?

Related

Why does C# not support immutable properties in Interfaces?

I just found out after trying to implement an immutable interface property, that C# apparently does not support the behavior that I am looking for. What I planned was quite simple, objects would subscribe to an interface that held an immutable generic property, that means a property without a setter. However, to my surprise, a subscribing class can still add the setter without any sort of error. In fact, it appears as though C# interfaces entirely ignore the signature of a property altogether. All it cares about is the property type and name.
For example:
namespace Some.Arbitrary.Framework
{
public interface IIdentifiable<T>
{
/// <summary>
/// Classes that subscribe to this interface
/// may still add a 'set;' signature.
/// </summary>
T Identifier { get; } // the lack of 'set;' is ignored
}
}
I've seen many posts on StackOverflow saying that C# does not support this behavior, but my question is: why does C# not support immutable properties in interfaces like I have described? Is there a fundamental design flaw behind what I am intending to do?
Because interfaces define a contract. When you say that a contract requires a get, you say that the implementer must provide a get, you cannot say "you can only do this", so, given:
public interface IData
{
string Data { get; }
}
You are actually saying
public interface IData
{
string GetData();
}
The client can always do this:
public class Data : IData
{
public string Data { get; set; }
}
Because it's actually doing this:
public class Data : IData
{
public string GetData() {}
public void SetData(string data) {}
}
So, Data implements the IData contract, as far as IData cares.
The most similar structure you could use is this:
public interface IIdentifiable<T>
{
T Identifier { get; }
}
public abstract class IdentifiableBase<T> : IIdentifiable<T>
{
T Identifier { get; protected set; }
}
And make your classes implement IdentifiableBase<T>, or you could just keep the IdentifiableBase class and leave the interface behind altogether.

C# Generic class as parameter with same T as called method of generic class

I would like call:
Question<Entity> question =
Question<Entity>.Create(
Choice.Create().
AddFollowUpQuestion(Question.Create()).
AddFollowUpQuestion(Question.Create()),
Choice.Create()
);
But the best C# allows me to do is:
Question<Entity> question =
Question<Entity>.Create(
Choice<Entity>.Create().
AddFollowUpQuestion(Question<Entity>.Create()).
AddFollowUpQuestion(Question<Entity>.Create()),
Choice<Entity>.Create()
);
I am trying to clean some code up, basically just adding syntactic sugar so some definitions I have to make a lot of are easier to read.
Both intelisense and the compiler know they are expecting the parameter to be of type Choice because it is a method of the generic class. But it still requires me to type out the type of T for the passed argument.
A bit more abstract: I am trying to create a top level generic class in which all properties which are also generic types will be using the same type for T.
Can anyone help me solve this puzzle? Or at least explain me why I have to type the same Type over and over again?
Simplified class definitions:
public class Question<T> where T : Entity
{
public static Question<T> Create(params Choice<T>[] choices)
{
return new Question<T>
{
Choices = choices
};
}
private Choice<T>[] Choices { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
public Choice<T> AddFollowUpQuestion(Question<T> followUpQuestion)
{
FollowUpQuestions.Add(followUpQuestion);
return this;
}
private static List<Question<T>> FollowUpQuestions { get; set; }
}
public abstract class Entity
{
}
C# can infer the method that you want to call based on the type of a parameter, but it cannot infer the type of the class on which to call a method that produces a parameter of the required type: the "type inference magic" goes only one way.
Essentially, you giving the compiler Choice.Create() expression and the fact that its result is being passed to a method expecting Choice<Entity>, and asking it to deduce that Choice is actually a generic type (despite the fact that there may be a non-generic Choice in the system), and it has a Create() method that returns Choice<T>. Although the compiler could possibly do it, implementation would be expensive, and could potentially be a breaking change.
However, you can make a generic helper method that would provide the same T to multiple classes, like this:
static Question<T> MakeQuestion<T>() {
return Question<T>.Create(Choice<T>.Create());
}
Now you can call
Question<Entity> question = MakeQuestion<Entity>();
and pass the type parameter only once.
Edit: As far as the more elaborate example from your edit is concerned, you should be able to shorten the API by introducing a factory that is generic on Entity, and lets you create questions, follow-ups, etc.
class QuestionFactory<T> {
public Question<T> CreateQuestion() {
...
}
public Choice<T> CreateChoice() {
...
}
}
Now you can do this:
var qf = new QuestionFactory<Entity>();
var question = qf.CreateQuestion(
qf.CreateChoice().
AddFollowUpQuestion(qf.CreateQuestion()).
AddFollowUpQuestion(qf.CreateQuestion()),
qf.CreateChoice()
);
A common thing to do is to create non-generic classes for the factory method:
public static class Question {
public static Question<T> Create<T>(Choice<T> choice) {
return Question<T>.Create(choice);
}
}
...
Question<Entity> question = Question.Create(Choice<Entity>.Create());
One way is to change Question.Create() to not expect a Choice to be provided, rather it creates the Choice itself. It makes the code a little simpler and you can achieve your goal.
public class Question<T> where T : Entity
{
public static Question<T> Create()
{
return new Question<T>
{
Choice = Choice<T>.Create()
};
}
private Choice<T> Choice { get; set; }
}
public class Choice<T> where T : Entity
{
public static Choice<T> Create()
{
return new Choice<T>();
}
}
public abstract class Entity
{
}
Depending on the context, this can be a positive change as the responsibility of creation of a Choice is moved to the Question, in other words you abstract the callers of Question.Create() from the hassle of creation of Choice.
On the other hand, it increases the coupling of Question and Choice.
Which one is prefered, depends on the rest of the architecture.
Of course, I assumed that T is really needed in Choice.

How to get base class object from closed constructed class in C#

Just another small C# training app, and just another Compilation Error, but it cannot just go away from me... I am just wondering, what I am doing wrong here:
public abstract class Material
{
}
public abstract class Cloth<T> where T:Material
{
public T Prop { get; set; }
}
public class Cotton : Material
{
}
public class Dress<T> : Cloth<T> where T : Material
{
}
public class Test
{
private Cloth<Material> cloth;
public Test()
{
/* below won't compile */
cloth = new Dress<Cotton>();
}
}
I want to get the base class object from a closed constructed class. Anyone ?
When trying to compile I get the error:
Cannot implicitly convert type Dress<Cotton> to Cloth<Material>
What you want to achieve is called covariance (see the following article for samples).
Unfortunately, there's no variance support for classes: it's restricted to interfaces and delegates.
Thus and alternatively, you might design an interface called ICloth<T> with T covariant:
public interface ICloth<out T>
{
T Prop { get; set; }
}
And implement it in any of your possible cloths, including Cloth<T>.
Now type cloth as ICloth<T> and your assignment should work (i.e. cloth = new Dress<Cotton>();), because Dress<Cotton> is ICloth<out T>, which is an interface with a T covariant generic parameter.
Learn more about generic interface with variance in the following article on MSDN.

Can I cast from an interface to a concrete type with another interface implementation

I should start by saying that I am very much a noobie with interfaces so this might be a really dumb question. Also apologies if my Title is unclear - matches the state of my mind!
I do understand the principles behind interfaces and I am want to use them here both to support unit testing and also decoupling via a DI Framework in what is horribly messy and un-testable legacy code.
I have an inteface called IDatHandler. It has a List<> property called Items. The concrete implementations should return a concrete type of IDatContainer. There are some methods of course but I have left them out
public interface IDatHandler
{
....
List<IDatContainer> Items
{
get; set;
}
}
This is a concrete implementation:
public class ADEColorHandler : IDatHandler
{
....
public List<ADEColor> Items
{
get; set;
}
}
}
ADEColor implements IDatContainer. The concrete implementation fails unless I replace ADEColor with IDatContainer.
Is there a way to get Items returned as a list of type ADEColor or am I just breaking the rules?
I should have said that this app is currently using NET 3.5
=========>>> The Answer - thanks Charleh!
The IDatHandler Interface
public interface IDatHandler<T> where T : IDatContainer
{
....
List<IDatContainer> Items
{
get; set;
}
}
The concrete Class:
public class ADEColorHandler : IDatHandler<ADEColor>
{
....
public List<ADEColor> Items
{
get; set;
}
}
}
My units tests on ADEColorHandler Assert against this list and pass.
You could go this route:
public interface IDatHandler
{
// Any common interface stuff
}
public interface IDatHandler<T> : IDatHandler
where T : IDatContainer
{
// Any generics
List<T> Items;
}
public class ADEColorHandler : IDatHandler<ADEColor>
{
....
public List<ADEColor> Items
{
get; set;
}
}
This does mean you need to do some casting at the other end though since if you just pass around IDatHandler instances, you need to know the generic type before you can query Items
What are you trying to achieve? That might help determine what you can use...
Alternatively you could use IEnumerable in your original interface implementation - do you need to know the concrete type of the collection at design time or can you get away with casting?
Edit: added the constraint above
Just trying to get my head round this because using the above interface will work to a certain degree but my assumption is that you want to loop through these to process them etc - I'm wondering if this would work (need to check)
List<IDatHandler<IDatContainer>> someList = new List<IDatHandler<IDatContainer>>();
someList.Add((IDatHandler<IDatContainer>)new ADEColorHandler());
Then you could enumerate the list... going to just check to see if this works.
Edit: nope, didn't work since the generic type is actually different at runtime. I'll have a mess around - I enjoy trying to work out what you can and can't do with generics!
Edit:
Ok so the best one is probably:
public interface IDatHandler<T> : IDatHandler
where T : IDatContainer
{
List<T> Items { get; set; }
}
public class ADEColorHandler : IDatHandler<IDatContainer>
{
public List<IDatContainer> Items
{
get;
set;
}
}
Which means you can do:
var items = new List<IDatHandler<IDatContainer>>();
items.Add(new ADEColorHandler());
then you can enumerate and get Items from each IDatHandler and query each IDatContainer. Of course you are hidden from the concrete types but I assume you have an interface on the containers to try and abstract those implementation details. This should be fine

Contravariance and Entity Framework 4.0: how to specify EntityCollection as IEnumerable?

I have specified a couple of interfaces, which I am implementing as entities using Entity Framework 4. The simplest demonstration code I can come up with is:
public class ConcreteContainer : IContainer
{
public EntityCollection<ConcreteChild> Children { get; set; }
}
public class ConcreteChild : IChild
{
}
public interface IContainer
{
IEnumerable<IChild> Children { get; set; }
}
public interface IChild
{
}
I receive the following compiler error from the above:
'Demo.ConcreteContainer' does
not implement interface member
'Demo.IContainer.Children'.
'Demo.ConcreteContainer.Children'
cannot implement
'Demo.IContainer.Children'
because it does not have the matching
return type of
'System.Collections.Generic.IEnumerable'
My current understanding is that this is because IEnumerable (which is implemented by EntityCollection) is covariant but presumably not contravariant:
This type parameter is covariant. That is, you can use
either the type you specified or any type that is more
derived. For more information about covariance and contravariance,
see Covariance and Contravariance in Generics.
Am I correct, & if so, is there any way I can achieve my goal of specifying the IContainer interface purely in terms of other interfaces rather than using concrete classes?
Or, am I misunderstanding something more fundamental?
The generic variance in .NET 4 is irrelevant here. The implementation of an interface has to match the interface signature exactly in terms of types.
For example, take ICloneable, which looks like this:
public interface ICloneable
{
object Clone();
}
It would be nice to be able to implement it like this:
public class Banana : ICloneable
{
public Banana Clone() // Fails: this doesn't implement the interface
{
...
}
}
... but .NET doesn't allow this. You can sometimes use explicit interface implementation work around this, like so:
public class Banana : ICloneable
{
public Banana Clone()
{
...
}
object ICloneable.Clone()
{
return Clone(); // Delegate to the more strongly-typed method
}
}
However, in your case you can't ever do that. Consider the following code, which would be valid if ConcreteContainer was considered to implement IContainer:
IContainer foo = new ConcreteContainer();
foo.Children = new List<IChild>();
Now your property setter is actually only declared to work with EntityCollection<ConcreteChild>, so it clearly can't work with any IEnumerable<IChild> - in violation of the interface.
As far as I understand, you must implement an interface - you can't assume that a covariant/contra-variant member would be picked up as a substitute.
Even if it was permissible, note that setter for children is an issue. Because it will allow to set property of type EntityCollection<ConcreteChild> with value of any other type such as List<ConcreteChild> or EntityCollection<ConcreteChild2> because both are implementing IEnumerable<IChild>.
In current design, I will implement IContainer privately in ConcreteContainer and check the input value in IEnumerable.Children setter for a compatible type. Another way to approach this design is to have generic interfaces such as:
public interface IContainer<T> where T:IChild
{
IEnumerable<T> Children { get; set; }
}
So you need to implement this interface, right?
public interface IContainer
{
IEnumerable<IChild> Children { get; set; }
}
But in the real class, you want the property to be of type EntityCollection<ConcreteChild>. Here’s how you can do this:
public class ConcreteContainer : IContainer
{
// This is the property that will be seen by code that accesses
// this instance through a variable of this type (ConcreteContainer)
public EntityCollection<ConcreteChild> Children { get; set; }
// This is the property that will be used by code that accesses
// this instance through a variable of the type IContainer
IEnumerable<ConcreteChild> IContainer.Children {
get { return Children; }
set {
var newCollection = new EntityCollection<ConcreteChild>();
foreach (var item in value)
newCollection.Add(item);
Children = newCollection;
}
}
}

Categories