Is it possible to have extra (ignored) properties in C#? - c#

I have a repository for a DocumentDb database. My documents all have a set of common properties so all documents implement the IDocumentEntity interface.
public interface IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
}
public class KnownDocument : IDocumentEntity {
[JsonProperty("id")]
Guid Id { get; set; }
[JsonProperty("documentClassification")]
DocumentClassification DocumentClassification { get; set; }
[JsonProperty("knownProperty")]
string KnownProperty { get; set; }
}
public class BaseDocumentRepository<T> where T : IDocumentEntity {
public Set(T entity) {
// ... stuff
}
}
This works fine with a KnownDocument where I know all of the properties. But, of course, what's great about a Document Db is that I don't need to know all of the properties (and in many cases I won't).
So my client submits something like this-
{unknownProperty1: 1, unknownProperty2: 2}
And I want to upsert this using my document repository.
public OtherDocumentService() {
_otherDocumentService = new OtherDocumentRepository();
}
public UpsertDocument(dynamic entity) {
entity.id = new Guid();
entity.documentClassification = DocumentClassification.Other;
_otherDocumentRepository.Set(entity);
}
But I get an InvalidCastException from dynamic to IDocumentEntity. I assume it's because of the extra properties that exist on the dynamic object but not on the IDocumentEntity interface?
What I'm trying to do is leave my document entities open to be dynamic, but rely on a few properties being there to maintain them.

Entity parameter passed to the UpsertDocument should explicitly implement IDocumentEntity in order do make the code works, it is not enough just have a Id property.
Some options:
1) Proxy may be applied:
public class ProxyDocumentEntity : IDocumentEntity
{
public dynamic Content { get; private set; }
public ProxyDocumentEntity(dynamic #content)
{
Content = #content;
}
public Guid Id
{
get { return Content.Id; }
set { Content.Id = value; }
}
}
... using
public void UpsertDocument(dynamic entity)
{
entity.Id = new Guid();
repo.Set(new ProxyDocumentEntity(entity));
}
The stored document will have nested Object property, which may be not acceptable
2)There is a lib https://github.com/ekonbenefits/impromptu-interface which creates a proxy dynamically
and does not make extra property like solution above.
Drawback will be in performance.
Technically it could be 2 methods:
public void UpsertDocument(IDocumentEntity entity){...}
public void UpsertDocument(dynamic entity){...}
so the first (fast) will work for the objects which implement IDocumentEntity and second(slow) for the rest of the objects.
But this is a speculation a bit , as I dunno the details of the whole code base of the project you have.

If you have some flexibility as to how to name those dynamic properties, you could stuff them into a Dictionary property on your object:
public Dictionary<string, dynamic> extra { get; set; }

Related

How to implement a generic method with multiple types?

I am working on accounting software, and I need help with generics.
I have multiple document types and depending on the type different posting rules will apply.
Now my question is how do I make everything generic?
I have tried this
public interface IDocument<IItem>
{
public Guid Id {get;set;}
public DocumentType DocumentType {get;set;} // enum
public List<IItem> Items {get;set;}
}
public interface IItem
{
public Guid Id {get;set;}
public double Net {get;set;}
public double Vat {get;set;}
public double Gross {get;set;}
}
public class PostDocument
{
public bool Post(IDocument<IItem> document)
{
foreach(item in document.Items)
{
// do something
}
}
}
The difficult thing here is that I will have multiple item classes because items for wholesale or retail are not the same(But every item class will have some common properties such as Net, Vat, and Gross). How would I get around it so I can have this generic method for all document types, so I don't have to write a method for every document type that my application will have?
If you don't expect to have thousands of document types, a reasonable way to approach this problem is to use the strategy pattern. There are a few different ways to approach the problem, but in a nutshell it is designed to swap one algorithm with another that has the same interface.
The pattern can also be used to switch between services that have a similar purpose based on a model object, similar to your IDocument<IItem> type.
Assumptions
You want to adhere to the Single Responsiblity Principle and Open/Closed Principle and take advantage of .NET generics.
It is certainly possible to achieve the following using casting, but it would involve modifying multiple types virtually every time you change something.
Document and Item Interfaces
First of all, we need some rework of the interfaces. For the design to work, we need both a generic and non-generic document interface. This gets us out of a common pitfall with trying to specify the closing type in places where it is not allowed, since C# generics are very strict and don't allow wildcards like some other languages do.
public interface IDocument
{
public Guid Id { get; set; }
}
public interface IDocument<TItem> : IDocument
where TItem : IItem
{
public IList<TItem> Items { get; set; }
}
public interface IItem
{
public Guid Id { get; set; }
public decimal Net { get; set; }
public decimal Vat { get; set; }
public decimal Gross { get; set; }
}
We declare IDocument<TItem> : IDocument where TItem : IItem to ensure that the properties of the concrete implementation of IItem are available to the rest of our code without casting.
Note the DocumentType enum was removed, as it is not necessary and redundant since we can check a document type as follows:
IDocument document = new RetailDocument();
if (document is RetailDocument retailDocument)
// do something with retailDocument
You can add it back if you feel you need it, though.
Concrete Document and Item Implementations
As others have pointed out in the comments, when dealing with currency we typically declare the type as decimal instead of double.
public class RetailItem : IItem
{
public Guid Id { get; set; }
public decimal Net { get; set; }
public decimal Vat { get; set; }
public decimal Gross { get; set; }
// Other properties
public string RetailStuff { get; set; }
}
public class WholesaleItem : IItem
{
public Guid Id { get; set; }
public decimal Net { get; set; }
public decimal Vat { get; set; }
public decimal Gross { get; set; }
// Other properties
public string WholesaleStuff { get; set; }
}
public class RetailDocument : IDocument<RetailItem>
{
public Guid Id { get; set; }
public IList<RetailItem> Items { get; set; }
}
public class WholesaleDocument : IDocument<WholesaleItem>
{
public Guid Id { get; set; }
public IList<WholesaleItem> Items { get; set; }
}
DocumentStrategy and DocumentPoster Interfaces
To make your strategy classes (the part that handles the post) generic, we need an interface for it. We also provide an (optional) IDocumentPoster interface, which would come in handy if you are using dependency injection.
PostDocument was named DocumentPoster because in C# we name methods after verbs and classes/properties after nouns.
public interface IDocumentStrategy
{
bool Post<TDocument>(TDocument document) where TDocument : IDocument;
bool AppliesTo(IDocument document);
}
public interface IDocumentPoster
{
bool Post(IDocument document);
}
DocumentStrategy Abstraction
Here is an abstract class that is used to hide the ugly details of casting to the concrete IDocument type so we can access the strongly-typed properties within the strategy implementations.
public abstract class DocumentStrategy<TDoc> : IDocumentStrategy
{
bool IDocumentStrategy.AppliesTo(IDocument document)
{
// Map the RetailDocument to this strategy instance
return document is TDoc;
}
bool IDocumentStrategy.Post<TDocument>(TDocument document)
{
return Post((TDoc)(object)document);
}
protected abstract bool Post(TDoc document);
}
Concrete Document Strategy Implementations
public class RetailDocumentStrategy : DocumentStrategy<RetailDocument>
{
protected override bool Post(RetailDocument document)
{
// Post RetailDocument...
// Note that all of the properties of RetailDocument will be avalable here.
//var x = document.Items[0].RetailStuff;
return true;
}
}
public class WholesaleDocumentStrategy : DocumentStrategy<WholesaleDocument>
{
protected override bool Post(WholesaleDocument document)
{
// Post WholesaleDocument...
// Note that all of the properties of WholesaleDocument will be avalable here.
//var x = document.Items[0].WholesaleStuff;
return true;
}
}
NOTE: You specified you don't want to write a method for every document type, but you sort of have to if you have different properties that you are reading in each case. If you have any common processing code that you want to share between your strategy implementations, it is usually better to inject a service that handles the common functionality into the constructor of the strategies than to put the common code in DocumentStrategy<TDoc>. That way, if you have a new strategy that doesn't use the common functionality, you can simply omit the injection on that one class.
var documentPosterService = new DocumentPosterService();
var strategies = new IDocumentStrategy[]
{
new RetailStrategy(documentPosterService),
new WholesaleStrategy(documentPosterService)
};
See the Usage section below to get an idea how to wire these strategies up. Note I am not showing the modifications to the RetailStrategy and WholesaleStrategy classes you will need to make to accept the extra service parameter, but it is similar to the DocumentPoster class below.
DocumentPoster Implementation
Here is the class that ties it all together. Its main purpose is to select the strategy based on the type of document that is being passed to it before delegating the task of processing the document to the strategy.
We provide the strategy implementations through the constructor so we can add/remove document strategies later without needing to change existing strategy implementations or DocumentPoster.
public class DocumentPoster : IDocumentPoster
{
private readonly IEnumerable<IDocumentStrategy> documentStrategies;
public DocumentPoster(IEnumerable<IDocumentStrategy> documentStrategies)
{
this.documentStrategies = documentStrategies
?? throw new ArgumentNullException(nameof(documentStrategies));
}
public bool Post(IDocument document)
{
return GetStrategy(document).Post(document);
}
private IDocumentStrategy GetStrategy(IDocument document)
{
var strategy = documentStrategies.FirstOrDefault(s => s.AppliesTo(document));
if (strategy is null)
throw new InvalidOperationException(
$"Strategy for {document.GetType()} not registered.");
return strategy;
}
}
Usage
var poster = new DocumentPoster(
new IDocumentStrategy[] {
new RetailDocumentStrategy(),
new WholesaleDocumentStrategy()
});
var retailDocument = new RetailDocument()
{
Id = Guid.NewGuid(),
Items = new List<RetailItem>
{
new RetailItem() { Id = Guid.NewGuid(), Net = 1.1m, Gross = 2.2m, Vat = 3.3m, RetailStuff = "foo" },
new RetailItem() { Id = Guid.NewGuid(), Net = 1.2m, Gross = 2.3m, Vat = 3.4m, RetailStuff = "bar" },
}
};
poster.Post(retailDocument);
var wholesaleDocument = new WholesaleDocument()
{
Id = Guid.NewGuid(),
Items = new List<WholesaleItem>
{
new WholesaleItem() { Id = Guid.NewGuid(), Net = 2.1m, Gross = 3.2m, Vat = 4.3m, WholesaleStuff = "baz" },
new WholesaleItem() { Id = Guid.NewGuid(), Net = 3.2m, Gross = 4.3m, Vat = 5.4m, WholesaleStuff = "port" },
}
};
poster.Post(wholesaleDocument);

ViewModel Object Convert to Entity Framework Object

Goal: to save ViewModel object by Entity Framework. I have UserViewModel object which has list of UnitViewModel. Then, I have a UserAdapter class which converts UserViewModel into Entity Framework User object (see Convert()below how).
Now, my question is how do I convert this list of UnitViewModel to its corresponding Entity Framework Unit list? - Do I have to get each object from DB Context by calling something like context.Units.Where(u=>myListofUnitIDs.Contains(u.UnitID))?
public class UserViewModel
{
public Guid? UserID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public DateTime? CreateTime { get; set; }
public List<UnitViewModel> UserUnits { get; set; }
}
public class UnitViewModel
{
public Guid UnitID { get; set; }
public string Name { get; set; }
public int? SortIndex { get; set; }
public DateTime CreateTime { get; set; }
public bool Assigned { get; set; }
}
public class UserAdapter
{
public static User Convert(UserViewModel userView)
{
User user;
if (userView.UserID.HasValue)
{
using (var provider = new CoinsDB.UsersProvider())
{
user = provider.GetUser(userView.UserID.Value);
}
}
else
{
user = new User();
}
user.FirstName = userView.FirstName;
user.LastName = user.LastName;
user.Password = StringHelper.GetSHA1(userView.Password);
user.UserName = user.UserName;
user.CreateTime = DateTime.Now;
// Problem here :)
// user.Units = userView.UserUnits;
return user;
}
}
UPDATE: The main concern here is that I have to retrieve each Unit from database to match (or map) it with ViewModel.Unit objects, right? Can I avoid it?
For your information, this operation is called as Mapping mainly. So, you want to map your view model object to the entity object.
For this, you can either use already existed 3rd party library as AutoMapper. It will map properties by reflection which have same name. Also you can add your custom logic with After method. But, this approach has some advantages and disadvantages. Being aware of these disadvantages could help you to decide whether you must use this API or not. So, I suggest you to read some articles about advantages and disadvantages of AutoMapper especially for converting entities to other models. One of such disadvantages is that it can be problem to change the name of one property in the view model in the future, and AutoMapper will not handle this anymore and you won't get any warning about this.
foreach(var item in userView.UserUnits)
{
// get the mapped instance of UnitViewModel as Unit
var userUnit = Mapper.Map<UnitViewModel, UserUnit>(item);
user.Units.Add(userUnit);
}
So, I recommend to write your custom mappers.
For example, I have created a custom library for this and it maps objects lik this:
user.Units = userView.UserUnits
.Select(userUnitViewModel => userUnitViewModel.MapTo<UserUnit>())
.ToList();
And I am implementing these mapping functions as:
public class UserUnitMapper:
IMapToNew<UnitViewModel, UserUnit>
{
public UnitViewModel Map(UserUnit source)
{
return new UnitViewModel
{
Name = source.Name,
...
};
}
}
And then in runtime, I am detecting the types of the objects which will be used during mapping, and then call the Map method. In this way, your mappers will be seperated from your action methods. But, if you want it urgently, of course you can use this:
foreach(var item in userView.UserUnits)
{
// get the mapped instance of UnitViewModel as Unit
var userUnit= new UserUnit()
{
Name = item.Name,
...
};
user.Units.Add(userUnit);
}

Config Automapper to ignore type when it's an inner-inner property but not inner property

This one takes a little explaining. I have a set of types such that;
public class Child
{
public int ID { get; set;}
}
public class MayHaveChild
{
public Child Value { get; set; }
public int MayID { get; set; }
}
public class MustNotHaveChild { get; set; }
{
public List<MayHaveChild> MayValues { get; set; }
}
In the above scenario, I want any mapping of MayHaveChild to have the values for the Child object, except when I have mapped MustNotHaveChild. E.g.;
When I have
//...some code
MayHave obj = Mapper.Map<MayHaveChild>(childObj);
// I want to be able to access obj.Child.ID
But when I have
//...some code
MustNotHave obj = Mapper.Map<MustNotHaveChild>(notHaveObj);
// I want to be able to access obj.MayValues[0].MayID but
// *not* obj.MayValues[0].Value
I've been through the automapper documention on nesting, polymorphism, lists, etc and I can't find anything that quite matches what I want.
I could solve this by having a inheriting the MayHave class to a MustNotHave variant but this would involve changing quite a lot of existing code. Is there a way to configure Automapper in the manner I need?
I couldn't find a way to configure AutoMapper the way I wanted without going down the inheritance route - though this proved less problematic than I thought. I did something like the following;
public class NoChild : MayHaveChild
{
}
public class MustNotHaveChild { get; set; }
{
// \/--datatype change here
public List<NoChild> MayValues { get; set; }
}
Then, later in the AutoMapper config;
Mapper.CreateMap<MayHave, NoChild>()
.ForMember(c => c.Child, opt => opt.Ignore());

How can I loosely couple database columns in a .NET application?

I have two versions of an almost identical database. Below I have created an Example table to demonstrate the basic differences, namely the ID column has changed from an Integer Identity to a GUID and various properties have been updated, in the Example archived has been replaced with readOnly and hidden:
Legacy version:
CREATE TABLE Example
(
--Data Identity (maps to DbId in the example code)
Id int IDENTITY PRIMARY KEY,
--Example columns
SomeValue varchar(50),
AnotherValue int,
--Data Properties
Archived bit
)
New version:
CREATE TABLE Example
(
--Data Identity (maps to DbId in the example code)
Id uniqueidentifier PRIMARY KEY,
--Example columns
SomeValue varchar(50),
AnotherValue int,
--Data Properties
ReadOnly bit,
Hidden bit
)
I need to be able to use an O/R mapper such as NHibernate to connect to one or other of these database versions. I would like to be able to tell the application which version to use through settings in a configuration file.
My initial plan was to create a common interface for the business logic and use an IoC container such as Unity to swap between the relevant concrete classes in the configuration file.
Below is an example of the code I created to test this theory:
public interface IDataIdentity
{
object Id { get; }
}
public class LegacyDataIdentity : IDataIdentity
{
public virtual long DbId { get; set; }
public object Id
{
get { return DbId; }
}
}
public class NewDataIdentity : IDataIdentity
{
public virtual Guid DbId { get; set; }
public object Id
{
get { return DbId; }
}
}
public interface IDataProperties
{
bool ReadOnly { get; set; }
bool Hidden { get; set; }
}
public class LegacyDataProperties : IDataProperties
{
public virtual bool Archived { get; set; }
public bool ReadOnly
{
get { return Archived; }
set { Archived = value; }
}
public bool Hidden
{
get { return Archived; }
set { Archived = value; }
}
}
public class NewDataProperties : IDataProperties
{
public virtual bool ReadOnly { get; set; }
public virtual bool Hidden { get; set; }
}
public class DataItem
{
public DataItem(IDataIdentity dataIdentity, IDataProperties dataProperties)
{
DataIdentity = dataIdentity;
DataProperties = dataProperties;
}
public IDataIdentity DataIdentity { get; set; }
public IDataProperties DataProperties { get; set; }
}
public class Example : DataItem
{
public Example(IDataIdentity dataIdentity, IDataProperties dataProperties)
: base(dataIdentity, dataProperties)
{
}
public virtual string SomeValue { get; set; }
public virtual int AnotherValue { get; set; }
}
Can anyone advise if this is possible (specifically with Unity and NHibernate) and if so how to create the relevant NHibernate mapping files?
Alternatively, can anyone suggest any solution to the problem using any other methods or other IoC and O/R mapping tools (commercial or open source)?
Many thanks,
Paul
Why not abstract your data provider, implementing 2 versions (one with nhibernate mappings for the legacy data item, and one for the new data item).
To paraphrase your code slightly (simplified for clarity):
public abstract class AbstractData
{
public abstract string SomeValue { get; set; }
public abstract bool ReadOnly { get; set; }
//etc.
}
public interface IDataProvider
{
AbstractData Get(object id);
}
public class LegacyData : AbstractData
{
// Implement AbstractData, and
public virtual long Id { get { return m_Id; } set { m_Id = value; };
private long m_Id;
}
public class LegacyDataNHibernateProvider : IDataProvider
{
public LegacyDataProvider()
{
// Set up fluent nhibernate mapping
}
public AbstractData Get(object id)
{
// Interpret id as legacy identifier, retrieve LegacyData item, and return
}
};
// Same again for new data provider
This way, you aren't tied to nhibernate (or a database, for that matter), and you can specify concrete classes with correctly typed identifiers (which nhibernate can handle). This is the approach I'm taking, where I currently have to map against an existing database's SPs, but will later migrate to a new ORM-based system.
Maybe I'm not understanding your question correctly, but it sounds to me like you need to implement something like the "Factory Pattern".
I recently used the factory pattern to code (c#) to two data layers when the company I work for was switching from JDE to SAP. I was able to flip a config switch to switch between the two data layers, and the GUI wouldn't know any different.
Here's a couple links I found:
http://msdn.microsoft.com/en-us/library/ms954600.aspx
http://www.allapplabs.com/java_design_patterns/factory_pattern.htm
http://en.wikipedia.org/wiki/Abstract_factory_pattern
As far as NHibernate goes, I'm not familiar with it... sorry. Hope this helps.
Hard to recommend without knowing the full picture, but.... You can create an abstruction in the SPs by having SP return identical dataset for both table structures.
Another abstruction I am thinking of, is you can actually specify different hybernate mapping files, and initialize Hibernate with a different file depending on what database you connect to.

Design problem: Get child object type information avoiding if statements in presentation layer

I have a customer hierarchy like so:
abstract class Customer {
public virtual string Name { get; set; }
}
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
}
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
}
When I retrieve a Customer, I would like to show on the web form the properties to edit/modify. Currently, I use if statements to find the child customer type and show the specialized properties. Is there a design pattern (visitor?) or better way so I can avoid the "if" statements in presentation layer? How do you do it?
Further information: This is an asp.net website with nHibernate backend. Each customer type has its own user control on the page that I would like to load automatically given the customer type.
Can you use reflection to get the list of properties specific to an subclass (instance)? (Less error-prone.)
If not, create a (virtual) method which returns the special properties. (More error prone!)
For an example of the latter:
abstract class Customer {
public virtual string Name { get; set; }
public virtual IDictionary<string, object> GetProperties()
{
var ret = new Dictionary<string, object>();
ret["Name"] = Name;
return ret;
}
}
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
public override IDictionary<string, object> GetProperties()
{
var ret = base.GetProperties();
ret["Max spending"] = MaxSpending;
return ret;
}
}
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
public override IDictionary<string, object> GetProperties()
{
var ret = base.GetProperties();
ret["Award"] = Award;
return ret;
}
}
You probably want to create sections (fieldsets?) on your Web page, anyway, so if would come into play there, making this extra coding kinda annoying and useless.
I think a cleaner organization would be to have a parallel hierarchy of display controls or formats. Maybe use something like the Abstract Factory Pattern to create both the instance of Customer and of CustomerForm at the same time. Display the returned CustomerForm instance, which would know about the extra properties and how to display and edit them.
new:
interface CustomerEdit
{
void Display();
}
edit:
abstract class Customer {
protected CustomerEdit customerEdit; // customers have an object which allows for edit
public virtual string Name { get; set; }
public void Display() { customerEdit.Display(); } // allow the CustomerEdit implementor to display the UI elements
}
// Set customerEdit in constructor, tie with "this"
class HighValueCustomer : Customer {
public virtual int MaxSpending { get; set; }
}
// Set customerEdit in constructor, tie with "this"
class SpecialCustomer : Customer {
public virtual string Award { get; set; }
}
usage:
Customer whichCouldItBe = GetSomeCustomer();
whichCouldItBe.Display(); // shows UI depeneding on the concrete type
Have you tried something like this:
public class Customer<T>
where T : Customer<T>
{
private T subClass;
public IDictionary<string, object> GetProperties()
{
return subClass.GetProperties();
}
}
With a subclass of:
public class FinancialCustomer : Customer<FinancialCustomer>
{
}
This is off the top of my head so might not work. I've seen this type of code in CSLA.NET.
Here's the link to the CSLA.NET class called BusinessBase.cs which has a similar definition to what I've given above.

Categories