Passing different content that implements the same interface - c#

I have multiple Linq2Sql Classes such as "Article" "NewsItem" "Product".
They all have a title, they all have a unique ID and they all have a Summary.
So, I created an interface called IContent
public interface IContent {
int Id { get; set; }
String Title { get; set; }
String Summary { get; set; }
String HyperLink { get; set; }
}
In my code, I'm trying to make it possible to pass a List<T> that implements IContent and then use those common properties that I have implemented in each of the partial classes in my project.
So, just to clarify
Article is a Linq Entity.
I create a partial class and implement IContent Here's a snippet of Article.cs:
#region IContent Members
public int Id {
get {
return this.ArticleID;
}
set {
this.ArticleID = value;
}
}
Pretty Simple. In my code I'm trying to this, but I don't know where I'm going wrong:
List<IContent> items;
MyDataContext cms = new MyDataContext();
items = cms.GetArticles();
// ERROR: Can not implicitly convert List<Article> to List<IContent>
If my Article class implement IContent why can't I pass in Articles? I don't know what the objects that are going to be passed in.
I know I can do this with Inheriting a base class, but using LinqToSQL doesn't use regular objects.
I'm sure it's something simple that I'm missing.

This is because the List class and interface aren't covariant. If you're using .NET 4.0 and C# 4.0, you can actually use covariance on the IEnumerable<> interface, which should be okay for LINQ applications.
There's a good FAQ covering those topics.

Have you tried
items = cms.GetArticles().Cast<IContent>().ToList();

This is classic case that calls for co-variance in C# 4.0. You only have to change List<Article> to IEnumerable<Article> to make this assignemnt work:
IEnumerable<IContent> articles = myContext.GetArticles();
If you are stuck with .NET 3.5 you can just use Linq Cast<T>():
IEnumerable<IContent> articles = myContext.GetArticles().Cast<IContent>();

Related

Design Pattern to use for customizable/extendable classes with constructors

Starting with the use case.
Let's consider the base for this questions is a big framework and implementations of business objects of some software.
This software hast to be customized quite regularly, so it would be preferred that most of the C# objects are extendable and logic can be overriden. Even "model data".
The goal would be to be able to write code, create objects with input parameters - that may create more objects etc - and you don't have to think about whether those objects have derived implementations in any way. The derived classes will be used automatically.
For ease of uses a typesafe way to create the objects would be preferred as well.
A quick example:
public class OrderModel
{
public int Id { get; set; }
public string Status { get; set; }
}
public class CustomOrderModel : OrderModel
{
public string AdditionalData { get; set; }
}
public class StockFinder
{
public Article Article { get; }
public StockFinder(Article article)
{
Article = article;
}
public virtual double GetInternalStock() { /*...*/ }
public virtual double GetFreeStock() { /*...*/ }
}
public class CustomStockFinder : StockFinder
{
public bool UsePremiumAvailability { get; }
public CustomStockFinder(Article article, bool usePremiumAvailability)
: base(article)
{
UsePremiumAvailability = usePremiumAvailability;
}
protected CustomStockFinder(Article article) : this(article, false) { } // For compatibility (?)
public override double GetFreeStock() { /*...*/ }
}
In both cases I wanna do stuff like this
var resp = Factory.Create<OrderModel>(); // Creates a CustomOrderModel internally
// Generic
var finderGeneric = Factory.Create<StockFinder>(someArticle);
// Typesafe?
var finderTypesafe1 = Factory.StockFinder.Create(someArticle); // GetFreeStock() uses the new implementation
var finderTypesafe2 = Factory.StockFinder.Create(someArticle, true); // Returns the custom class already
Automatically generating and compiling C# code on build is not a big issue and could be done.
Usage of Reflection to call constructors is okay, if need be.
It's less about how complicating some code generation logic, written code analyzers, internal factories, builders etc are, and more about how "easy" and understandable the framework solution will be on a daily basis, to write classes and create those objects.
I thought about tagging the relevant classes with Attributes and then generating a typesafe factory class automatically on build step. Not so sure about naming conflicts, or references that might be needed to compile, as the constructor parameters could be anything.
Also, custom classes could have different constructors, so they should be compatible at each place in default code where they might be constructed already, but still create the custom object. In the custom code then you should be able to use the full custom constructor.
I am currently considering several different cases and possibilities, and can't seem to find a good solution. Maybe I am missing some kind of design pattern, or am not able to look outside of my bubble.
What would be the best design pattern or coding be to implement use cases like this?

Implement IList<ISomeInterface> with List<SomeObjectThatImplementsISomeInterface>

I have a set of interfaces using each others like this:
public interface IModel
{
string Name { get; }
IModelParameters Parameters { get; }
}
public interface IModelParameter
{
int Value { get; }
}
public interface IModelParameters: IList<IModelParameter>
{
void DoSomething();
}
And to implement those interfaces, I have defined those classes:
public class Model: IModel
{
string Name { get; internal set; }
public ModelParameters Parameters { get; private set; }
IModelParameters IModel.Parameters { get { return Factors; } }
}
public class ModelParameter: IModelParameter
{
int Value { get; internal set; }
}
public class ModelParameters: List<ModelParameter>, IModelParameters
{
void DoSomething()
{
// actual code
}
}
This does not compile because List<ModelParameter> implements IList<ModelParameter> and not IList<IModelParameter> as required by IModelParameters
Changing ModelParameters to be List<IModelParameter> fixes the compilation but it breaks Entity Framework migration generation because it no longer recognizes the list as a navigation property because the type parameter is an interface, not a regular class.
I could also have ModelParameters not implement IModelParameters and declare a second class that gets instantiated and filled directly in the IModelParameters.Factors getter inside Model
But this feels inefficient as it effectively creates two instances of the same list, one for Entity framework and a temporary one for use by the rest of the application. And because this temporary is filled at runtime, it introduces another potential point of failure.
This is why I'm trying to find a way to express the fact List<ModelParameter> implements IList<IModelParameter> just fine because ModelParameter implements IModelParameter itself.
I have a feeling that covariance/contravariance might be of help here, but I'm not sure how to use that.
You cannot do this. It it was possible to cast a List<ModelParameter> to IList<IModelParameter> you could try adding a object of another type to the list, i.e. class MyOtherModelParam : IModelParameter. And that is a contradiction since the type system guarantees that the list only contains ModelParameter objects.
You could replace it with IReadOnlyList<T>, since this interface do not expose any add or set methods it is safe to cast a List<ModelParameter> to IReadOnlyList<IModelParameter>.
Another possible solution would be to just remove the interface. If you intend to have only one implementation of IModelParameter, the interface serves little purpose, and you might as well just remove it.

Using Clone() to duplicate an ASP.NET MVC / EntityFramework model object

I've read this question about using Clone() and want to know if what I'm after will be achieved. My understanding from reading that question is that Clone() does a shallow copy, however reading elsewhere led me to believe differently, and now I'm confused.
Our project has a class Rule that has an ICollection<ICondition> Conditions. We'd like to provide users with a shortcut method to duplicate an existing Condition and modify it rather than start from scratch. To that end, we're providing a Copy To New button.
ICondition looks like this:
interface ICondition
{
long ID { get; set; }
string Description { get; set; }
DateTime EffectiveDate { get; set; }
string IfStatement { get; set; }
string PriceVersion { get; set; }
PriceDetail Pricing { get; set; }
bool StandardOption { get; set; }
}
Given what I've read about Clone(), I'm fairly confident it would work the way I expect by using ICondition newCondition = conditionToCopy.Clone(), though I'm unsure if Pricing would be duplicated correctly, since it's a complex data type.
So, the first part of my question is, "will this work?" I would just try it and see, however ICondition (or really its underlying Condition) doesn't seem to provide a method for Clone(), which leads me to the second part of my question: can I leverage IClonable to enable this functionality? If so, where?
Is this the way?
public static class Condition : IClonable
{
...
public Condition Clone(Condition conditionToClone)
{
return new Condition
{
Description = this.Description,
EffectiveDate = this.EffectiveDate,
IfStatement = this.IfStatement,
PriceVersion = this.PriceVersion,
Pricing = this.Pricing,
StandardOption = this.StandardOption
}
}
}
And, given that as the answer, is there any utility to declaring IClonable as the interface? Does it add any value?
Update:
Based on the below answer, I decided to do this, which at least builds (and hopefully runs; haven't tried it yet):
public class Condition
{
...
public Condition Clone()
{
return (Condition)base.MemberwiseClone();
}
}
I still don't see the need for ICloneable, so have left it out. The compiler was complaining about it anyway, something about the base class not being object.
There are couple of things. First Condition class should not be static. Second, PriceDetail class [Property pricing], Also need to impleemnt ICloneable. Instance class will allow base.MemberWiseClone() method.
public class Condition : ICloneable
{
public object Clone()
{
base.MemberwiseClone();
}
}

Compact syntax for static Create() method on generic class?

I have a pair of classes. These are literally copy/paste from my project:
public static class PageResult
{
public static PageResult<T> Create<T>(int totalCount, IList<T> items)
{
return new PageResult<T>()
{
TotalCount = totalCount,
Items = items,
};
}
}
public class PageResult<T>
{
public int TotalCount { get; set; }
public IList<T> Items { get; set; }
}
The reason I did this is so that I could use PageResult.Create(5, listOf5Items) as opposed to any other lengthier syntax. I didn't put the Create method in the PageResult(T) class because I'm pretty sure that requires me to type PageResult<int>(5, listOf5Numbers) instead, and that's an extra five characters...
But having two classes for it seems pretty lame. Is there a way I can get the more compact syntax without having a throwaway class just to store it?
As you already noted, you'd have to specify type parameters to even access the Create function, because that specific PageResult<T> class won't even exist until the JIT creates it when a method starts calling it. See Tuples for an instance of the .NET Framework itself doing just this pattern for the basically the same reason.
Note that another option is to make the PageResult class non-static, and inherit PageResult<T> : PageResult which will allow you to store a collection of PageResult objects without a type parameter. This can also be useful if you use an abstract PageResult
No. You could potentially make a VS snippet (or some other plugin/tool that could generate source code) to have some of the boilerplate typed out for you, but at the end of the day that code will need to be there.

Proto-buf .NET Serialization of complex inheritance interfaces

I would like to serialize for classes which do implement several interfaces some inheriting from the same base interface. Currently i use the BinaryFormatter, but i would love to use proto-buf .NET. But i think currently i would face issues similar to this described problem:
how to serialize a class implements two interfaces who have same based interface
The only possible solution i currently think of would be a wrapper around my classes which serializes a simpler data class which i use to create my complex classes.
Let me try to explain it further, like in the cited example i have a structure like this:
public interface IProduct
{
string SomeMethod();
}
public interface ISimpleProduct : IProduct
{
int SomeProperty { get; }
}
public interface IConstructionProduct : IProduct
{
int AnotherProperty {get;
}
public class ConcreteProduct : ISimpleProduct , IConstructionProduct
{
int SomeProperty {get; set;}
int AnotherProperty {get; set;}
string SomeMethod()
{
return "A concrete Product";
}
}
Now i wish to serialize ConcreteProduct, as i thought this is not possible currently in proto-buf .net i was considering to have a wrapper data class, like this:
public class ProductData
{
int[] PropertyValues { get; set;}
}
and to add to the IProductInterface a method to build each concrete product, like
public interface IProduct
{
string SomeMethod();
IProduct BuildProduct(ProductData data);
ProductData ToData();
}
Of course ProductData would be more sophisticated in reality but just for the concept. I would serialize now ProductData. I would not like to change the interface setup in the Product ConcreteProduct class as these interfaces are needed for further stuff later on. What i like about this approach, that issues with extensions could be dealt with in the BuildProduct implementations.
And again, i am a newbie, so if anything is just plain nonsense, sorry for that and correct me.
# Marc, i know you are author, thx a lot for that stuff, but more for other posts (i am not using proto-buf yet though) for example on DataTable stuff, already your post about the autogenerate columns saved a lot of time for me.
That sounds like you're going for the union types approach. You want to make a single serialization format that fits all your products. Additionally, you want each of your products to map to that union type and map back.
So you're remaining concern is on how to do the mapping. Honestly, I don't think you'll be happy in the long run with these two methods in the IProduct interface. And I hope you're aware that you need to deal with the problem of deserialization: Which type do you actually instantiate? Let me put it this way: With your code, you'll have to call new ConcreteProduct().BuildProduct(data) to get your ConcreteProduct. And the question is: How do you know it's a ConcreteProduct that you have to instantiate? The code that wants to call BuildProduct needs to know this! You could cut those methods and create a separate infrastructure for your mapping tasks. Here's what a factory method pattern would look like for this kind of problem:
public interface IProductMapper {
IProduct Unmap(ProductData data);
ProductData Map(IProduct product);
}
public static class ProductMapperFactory {
public static IProductMapper GetMapper(ProductData data) {
if (data.Type == "ConcreteProduct") return new ConcreteProductMapper();
else if ...
}
public static IProductMapper GetMapper(IProduct product) {
if (product is ConcreteProduct) return new ConcreteProductMapper();
else if ...
}
}
public class ConcreteProductMapper : IProductMapper {
public IProduct Unmap(ProductData data) {
var product = new ConcreteProduct();
// map properties
return product;
}
public ProductData Map(IProduct data) {
var data = new ProductData();
// map data
return data;
}
}
You see, the crucial line is data.Type == "ConcreteProduct": Somehow you must specify the kind of product in the data in order to know which kind of product to instantiate when mapping back from the union type.
Another difficulty that I see with union types in general is de/serialization of object graphs. Since you have your own serialization types, you need to write your own code to de/compose object graphs. If you're a newbie as you say, that'll probably put you into a world of hurt (or world of learning if you prefer :-p).
In any case, does it really need to be interfaces that you want to de/serialize? Would it be possible to instead create a class hierarchy where you're starting from a Product base class from which all other products derive and which carries the necessary includes. I assume this would create less troubles (with protobuf at least).
And finally, the master question: Why do you want to switch from the BinaryFormatter to protobuf exactly?

Categories

Resources