I've just read about the repository pattern in c#. It will provide an interchangeable layer for how the actual data is accessed. That's great. However, consider the following:
I have an XmlPersonRepository which will fetch XML data from a file and return it as a c# object (Person.cs POCO). Now I want the physical source of the XML data to be interchangeable too. Originally, it comes from a file, but it can also come from a web server or from a resource string. How would I implement this in the most reusable way? I don't want to write something like XmlPersonFromFileRepository and a XmlPersonFromWebRepository, because it would mean code duplication. It would duplicate the code for converting the raw XML data into a c# object, but this code stays the same, no matter if i fetch XML from a file or from a web service. So it's redundant to have the conversion code in both classes.
So in a nutshell, I want to have two abstraction layers: One layer which fetches the psysical XML data from whatever source, and another layer which converts this data into c# objects. Both should be interchangeable.
How can I implement this? And please tell me if this is a good idea or not, am I on the right track?
Simple. You just worded it in your question.
You have two problems to solve:
Get XML data from a source
Convert XML data to C# Object
To implement the first problem:
- IXmlDataGetter, an interface getting a single XML data from a source.
public interface IXmlDataGetter {
XmlData GetData(XmlDataName name);
}
"XmlData" should be either a byte[] or a Stream (Because XML contains metadata with regards to the encoding of data, I think it should be kept at byte level) or be a DOM Tree (like XmlNode). You choose the solution that fits you best.
"XmlDataName" is the way you identify a your stored data. Data has a name, however complex it may be. It may be just the string "PERSON" and the integer 25, being the id. The name of the data for the person with ID 25 may be the pair ("PERSON", 25).
This interface, can be implemented for DB:
public class DBXmlDataGetter : IXmlDataGetter {
XmlData GetData(XmlDataName name) {
return ResultOfQuery("SELECT xml_text FROM " + name.first /* PERSON */ + " WHERE ID=" + name.second /* 25 */);
}
}
This interface can also be implemented for a file:
public class FileXmlDataGetter : IXmlDataGetter {
XmlData GetData(XmlDataName name) {
return ContentsOfFile(name.first /* PERSON */ + "_" + name.second /* 25 */ + ".xml");
}
}
Of course "ResultOfQuery" and "ContentsOfFile" are just names of things I leave it to you to solve. And for the Web, build your URL from your XmlDataName the same way.
Now. Second problem, converting XML to C# object. You may use an XMLDeserializer, or parse the data with an XMLReader and build your object explicitly. You just have to create a class that does te job and takes the appropriate strategy as a constructor parameter:
public class XmlPersonRepository {
private readonly IXmlDataGetter _getter;
public PersonFetcher(IXmlDataGetter getter) {
_getter = getter;
}
Person GetFromId(int id) {
var xmlData = _getter.GetData(new XmlDataName("PERSON", id));
return ConvertToPerson(xmlData);
}
}
I won't get into the philosophical questions of IoC/Dependency injection here, but this is the basic pattern. The class that does the conversion just does the conversion. All it needs to perform the use case from end to end gets "injected" from "above".
You separated the responsibilities, now you're free to get your XML data from a user copy/paste in a textbox if you wish.
As said, check what Dependency Injection/Ioc is and have a look to some of the frameworks out there (like Ninject, Autofac etc).
In a nutshell you should create an interface IXmlPersonRepository that defines your methods and then implement it on all the different classes that will provide you the xml like
XmlFilePersonRepository : IXmlPersonRepository
XmlDBPersonRepository : IXmlPersonRepository
and so on.
You will then use the interface IXmlPersonRepository to do your calls. The DI bit will be responsible of the concrete implementation of your interface and it will be easy to swap between db, file etc.
Related
I'm trying to come up with a way to write a generic interface that can be implemented for multiple data stores, basically the generic type will specify the ID for the data in the data store (some of these data stores use strongly typed libraries, so you have to call something like long createNode(Node node))
For example the system we are using now, uses longs for the IDs, but if we made the transition (or use both at the same time) to something like SQL it would most likely be GUIDs. The entities a the business logic layer are pretty much set, think of it as basically a file system with a bunch of custom attributes on the nodes.
So far I tried something like this:
public interface DataThing<T>
{
T CreateThing(CustomEntity node);
CustomEntity GetThing(T ID);
}
public class LongDataThing : DataThing<long>
{
long CreateThing(CustomEntity node)
{
//...implement
}
CustomEntity GetThing(long ID)
{
//...implement
}
}
...do the same thing for GUID/Int/string...whatever
Then when it comes to instantiating the class to work with basically a factory design pattern is where I'm having problems. I thought I could do something like:
private DataThing myDataStore;
switch(config.dbtype)
{
case "longDB":
this.myDataStore = new LongDataThing();
break;
case: "stringDB":
this.myDataStore = new StringDataThing();
break;
//...etc.
}
But I can't create private DataThing myDataStore; without specifying it as long, string...etc, which means the business logic already has to know which type is being implemented instead of just asking the factory for a datastore object.
So what am I missing here? Can you not abstract out the datatype of an interface like this and have it transparent to the calling 'business logic' and figure out which implementation is desired from a config file or some other outside logic?
I realize there are loads of questions already posted regarding serialization of ADO.Net entities, but I haven't had any luck finding one that really addresses quite what I want to do.
Basically, I need a really bare-bones, shallow JSON or plain-object representation of an ADO.Net entity. The purpose is for change-logging; i.e. when a record is going to be changed, I want to snag a copy of its data "before" and "after", and log the change.
I don't want any of the navigation, complex or other properties to be considered; just the scalar properties of the entity. If I miss some data that only would appear in special cases, that's fine -- just trying to do a rough log. Ideally my final code should look something like this:
Employee emp = db.Employees.First();
string oldRecordJSON = MySerializer.serialize(emp);
emp.Name = "Fred";
db.saveChanges();
string newRecordJSON = MySerializer.serialize(emp);
ChangeLog.logDBChange("Employees", emp.ID, oldRecordJSON, newRecordJSON, DateTime.Now);
...Any quick & easy way to implement MySerializer.serialize?
Thanks!
If you're just wanting some specific properties of your employee, consider creating a basic model and serialising that.
var serializer = new JavaScriptSerializer();
serializer.Serialize(new MyEmployeeModel{ // set fields here});
You can build this as a converter if you wish, that's how I'd do it.
I have an interface, IConverter<TInputType, TOutputType> from which you can create a converter to inject (or whatever you want to do) into your code.
public interface IEmployeeFromDatabaseToBasicEmployeeModelConverter
: IConverter<TheDBType, MyEmployeeModel>{}
public class EmployeeFromDatabaseToBasicEmployeeModelConverter :
IEmployeeFromDatabaseToBasicEmployeeModelConverter
{
public MyEmployeeModel Invoke(TheDBType myDbTypeObject)
{
return new MyEmployeeModel{
// set properties.
}
}
}
In my current project, I have quite a few objects I need to persist to XML and inflate at runtime. I've been managing this through .NET's DataContracts. What I am doing right now is creating a separate class that represents the objects I'm serializing and reading/writing those to/from disc to avoid having too much responsibility in a single class. Here's an example:
public class Range
{
private float _min;
private float _max;
public float Min { get { return this._min; } }
public float Max { get { return this._max; } }
// Constructrs & Methods...
public SerializedRange GetAsSerializable();
}
The Range class has the complimentary class:
[DataContract]
public class SerializedRange
{
[DataMember]
public float Min;
[DataMember]
public float Max;
// Constructor...
}
My question then is, who should be responsible for actually taking the Serialized version of the object and inflating it into the actual object? I see three options, but I'm not sure which (if any of them) would be the best:
Give the Serialized version of the object an instance method that spits out an inflated instance, using the available constructors/factories of the sister class.
Give the sister class a factory that takes an instance of the serialized version to construct itself.
Don't have either the class or it's Serializable counterpart do anything- have the code that reads in the Serialized objects manually create the regular objects using whatever constructors/factories they'd regularly have.
I realize that in certain situations you'd have to do it one way or the other because of constraints outside of this somewhat contrived example. Since there's more then one way to do it though, what I'm really looking for is a general rule of thumb that yields neat, readable, and expandable code.
If you 'break' you application into constituent parts what logical components would you get? Here are few based on my understanding:
Domain Objects (Data that you are storing)
Data Layer - responsible for persisting the data (and retrieving it)
and many others (but just taken a subset as per your description)
Now, the job of the data layer is to write the content out to some storage - XML files to disk in your case.
Now, when you 'query' the file who fetches it? The data layer. Who 'should' populate the corresponding domain object? Well the data layer itself.
Should the data layer 'delegate' the responsibility of population to a separate class/factory? It depends if it's ever going to be reused by someone else. If not, concepts like inner classes can be of good help (they exist in the java world, not sure of it's equivalent in C#.NET). That way you'll have it modularized into a specific class, which is not publicly visible to other classes, unless you want it that way.
Should you go with factory? Yes, you may. But make sure it's logically correct to do so. You could land up with many object inflators - that could isolate the inflation functionality to one class and the factory could itself be a part of the data layer (if you want it that way).
Once you delineate the concerns you'll be in a better position to decided where to put that piece of code. I've provided some pointers that could come in handy.
Hope it helps...
How would you design an application (classes, interfaces in class library) in .NET when we have a fixed database design on our side and we need to support imports of data from third party data sources, which will most likely be in XML?
For instance, let us say we have a Products table in our DB which has columns
Id
Title
Description
TaxLevel
Price
and on the other side we have for instance Products:
ProductId
ProdTitle
Text
BasicPrice
Quantity.
Currently I do it like this:
Have the third party XML convert to classes and XSD's and then deserialize its contents into strong typed objects (what we get as a result of this process is classes like ThirdPartyProduct, ThirdPartyClassification, etc.).
Then I have methods like this:
InsertProduct(ThirdPartyProduct newproduct)
I do not use interfaces at the moment but I would like to. What I would like is implement something like
public class Contoso_ProductSynchronization : ProductSynchronization
{
public void InsertProduct(ContosoProduct p)
{
Product product = new Product(); // this is our Entity class
// do the assignments from p to product here
using(SyncEntities db = new SyncEntities())
{
// ....
db.AddToProducts(product);
}
}
// the problem is Product and ContosoProduct have no arhitectural connection right now
// so I cannot do this
public void InsertProduct(ContosoProduct p)
{
Product product = (Product)p;
using(SyncEntities db = new SyncEntities())
{
// ....
db.AddToProducts(product);
}
}
}
where ProductSynchronization will be an interface or abstract class. There will most likely be many implementations of ProductSynchronization. I cannot hardcode the types - classes like ContosoProduct, NorthwindProduct might be created from the third party XML's (so preferably I would continue to use deserialization).
Hopefully someone will understand what I'm trying to explain here. Just imagine you are the seller and you have numerous providers and each one uses their own proprietary XML format. I don't mind the development, which will of course be needed everytime new format appears, because it will only require 10-20 methods to be implemented, I just want the architecture to be open and support that.
In your replies, please focus on design and not so much on data access technologies because most are pretty straightforward to use (if you need to know, EF will be used for interacting with our database).
[EDIT: Design note]
Ok, from a design perspective I would do xslt on the incoming xml to transform it to a unified format. Also very easy to verify the result xml towards a schema.
Using xslt I would stay away from any interface or abstract class, and just have one class implementation in my code, the internal class. It would keep the code base clean, and the xslt's themselves should be pretty short if the data is as simple as you state.
Documenting the transformations can easily be done wherever you have your project documentation.
If you decide you absolutely want to have one class per xml (or if you perhaps got a .net dll instead of xml from one customer), then I would make the proxy class inherit an interface or abstract class (based off your internal class, and implement the mappings per property as needed in the proxy classes. This way you can cast any class to your base/internal class.
But seems to me doing the conversion/mapping in code will make the code design a bit more messy.
[Original Answer]
If I understand you correctly you want to map a ThirdPartyProduct class over to your own internal class.
Initially I am thinking class mapping. Use something like Automapper and configure up the mappings as you create your xml deserializing proxy's. If you make your deserialization end up with the same property names as your internal class, then there's less config to do for the mapper. Convention over Configuration.
I'd like to hear anyones thoughts on going this route.
Another approach would be to add a .ToInternalProduct( ThirdPartyClass ) in a Converter class. And keep adding more as you add more external classes.
The third approach is for XSLT guys. If you love XSLT you could transform the xml into something which can be deserialized into your internal product class.
Which one of these three I'd choose would depend on the skills of the programmer, and who will maintain adding new external classes. The XSLT approach would require no recompiling or compiling of code as new formats arrived. That might be an advantage.
NOTE: Sorry for the long question!
I'm trying to understand some key areas behind object orientation and I couldn't decide one way or another about my particular question.
Let's say I have an object full of lovely data. Class bob.
Bob myBob = new Bob("This string is data");
Let's say I want to save the contents of myBob to an xml file (bob.xml)
Should I have an object act on bob to write the contents out, or should I have myBob do this?
Case 1: Act on object
Writer myWriter = new Writer(myBob, "C:\\bob.xml");
Case 2: Save method
myBob.Save("C:\\bob.xml");
Some people are siding with option one as it means if the code for writing files is changed, it doesn't need to updated across every Save method; promoting code reuse I suppose. My problem with this is getting all the data out of objects which may have private data with no accessor.
The case for option two is that the method only acts on the data held by the object and that's the way it should be. No interference from other objects.
Or is the answer to my question one of those "case dependent" issues? If so, how do you know when one method is prefered over the other?
The correct approach, in general, is your Case 1. This maintains a single responsibility for the class (whatever it does) without coupling it to a specific persistence mechanism (a disk).
You're looking at a specific case of a more generalized problem: Serialization. It's good and OK for an object to have some means to indicate how it should be serialized-- it's the only entity that knows what's necessary to deserialize it, after all. But if you make the object save itself to disk, you've tightly coupled that object to a specific implementation.
Instead, consider creating an interface that a generalized "writer" can use to "serialize" the object to whatever that writer serializes to. This way, you'll be able to serialize to disk, to the network, to memory, to whatever you actually need to serialize to. :)
I would make Bob know how to serialize itself since it has private data. Another object (such as your Writer) would take that and put it on disk. Bob knows how to deal with its data best but it need not care about how or where that is stored. Your Writer knows how to save data best but it need not care about how that data is created.
This is an example of where the Strategy Design Pattern could be used. Your myBob object could have an instance of the class that will write it out. You may want the writer to implement an interface or derive from an abstract class so that the save routine can be easily changed.
Today you are saving to xml, but you might need to eventually persist the object to a database as well. This pattern will allow you to change the save routine easily. You would even have the option to change how you save at runtime.
I used to prefer option 2; however, as I have started really trying to understand and model the domains I am working on, I prefer option 1.
Imagine if your modelling Vehicles. Why would a vehicle know how to persist itself? It might know how to move, how to start and how to stop, but what is Save within the context of a vehicle.
One other method is to use the visitor pattern. Have your object contain an Accept method that goes through the members you want to process/serialize, and have a visitor be your serializer. Whenever you update or change your serialization (plain text to xml to binary to whatever), you don't need to update the object.
We've had good experiences at work doing it this way. It's pretty powerful.
Do this:
public interface Writable {
public void Save(Writer w);
}
public interface Writer {
public void WriteTag(String tag, String cdata);
}
public class Bob : Writable {
private String ssn = "123-23-1234";
public void Save(Writer w) {
w.WriteTag("ssn", ssn);
}
}
public class XmlWriter : Writer {
public XmlWriter(Sting filename) {...}
public void WriteTag(String tag, Sting cdata) {...}
}
Obviously this isn't a complete solution but you should get the general idea.
I think the correct approach is the Case 1, but your class may be defined this way to take advantage of both approaches:
class Bob {
IWriter _myWriter = null;
public Bob(){
// This instance could be injected or you may use a factory
// Note the initialization logic is here and not in Save method
_myWriter = new Writer("c://bob.xml")
}
//...
public void Save(){
_myWriter.Write(this);
}
// Or...
public void Save(string where){
_myWriter.Write(this, where);
}
//...
}
This could be easily modified to put the writing logic and initialization in a base class so Bob class is even cleaner and independent of the persistence.