Advice on filtering data and code reuse with Onion Architecture - linq-to-sql

Here are my questions and then I'll give you the background for them:
I would prefer to use Method 2 as my application design, so is there a way to provide filtering like Method 1 without introducing references to non-business code and without allowing access to the database model in the Core project?
How do you handle code reuse? The namespaces for each object are something like Project.Core.Domain or Project.Core.Services, but if feels weird making the namespace something like CompanyName.Core.Domain when it is not stored in that project. Currently, I'm copying the source code files and renaming namespaces to handle this, but I'm wondering if there is an organizational way to handle this or something else I hadn't thought of?
Technologies I'm using:
ASP.NET MVC 3
Linq-to-SQL
StructureMap
Moq
MSTest
Method 1:
Here's how I used to setup my web projects:
The Data project would contain all repositories, and Linq data contexts. In a repository, I would return a collection of objects from the database using IQueryable.
public IQueryable<Document> List()
{
return from d in db.Documents
select d;
}
This allowed me to setup filters that were static methods. These were also stored in the Data project.
public static IQueryable<Document> SortByFCDN(this IQueryable<Document> query)
{
return from d in query
orderby d.ID
select d;
}
In the service layer, the filter could be applied like this.
public IPagedList<Document> ListByFCDN(int page, IConfiguration configuration)
{
return repository.List().SortByFCDN().ToPagedList(page, configuration.PageSize, configuration.ShowRange);
}
Therefore, the repository would only have to provide a ListAll method that returned all items as an IQueryable object and then the service layer would determine how to filter it down before returning the subset of data.
I like this approach and it made my repositories cleaner while leaving the bulk of the code in the services.
Method 2
Here's how I currently setup my web projects:
Using the Onion Architecture:
Core: Contains business domain model, all interfaces for the application, and the service class implementations.
Infrastructure: Contains the repository implementations, Linq data contexts, and mapping classes to map the Linq database model to the business model.
Since I'm separating my business code from database code, I do not want to add references in the Core project to things like Linq to gain access to IQueryable. So, I've had to perform the filtering at the repository layer, map the database model to the domain model, and then return a collection of domain objects to the service layer. This could add additional methods into my repositories.

This is what I ended up doing:
1) Created a filtering enum object in the Core project.
public enum FilterType
{
SortFCDN
}
2) In the service class (also within the Core project), do something like:
public IPagedList<Document> ListByFCDN(int page)
{
Dictionary<FilterType, object> filters = new Dictionary<FilterType, object>();
filters.Add(FilterType.SortFCDN, "");
return repository.List(page, filters);
}
3) In the repository (under the Infrastructure project):
public IPagedList<Document> List(int page, Dictionary<FilterType, object> filters)
{
//Query all documents and map to the model.
return (from d in db.DbDocuments
select d).Filter(filters).Map(
page,
configuration.Setting("DefaultPageSize", true).ToInt(),
configuration.Setting("DefaultShowRange", true).ToInt());
}
4) Create a filters class in the Infrastructure project:
public static class DocumentFilters
{
public static IQueryable<DbDocument> Filter(this IQueryable<DbDocument> source, Dictionary<FilterType, object> filters)
{
foreach (KeyValuePair<FilterType, object> item in filters)
{
switch (item.Key)
{
case FilterType.SortFCDN:
source = source.SortFCDN();
break;
}
}
return source;
}
public static IQueryable<DbDocument> SortFCDN(this IQueryable<DbDocument> source)
{
return from d in source
orderby d.ID
select d;
}
}
The service layer (Core project) can then decide what filters to apply and pass those filters to the repository (Infrastructure project) before the query executes. Multiple filters can be applied as long as only one per FilterType is applied.
The filters dictionary can hold the type of filter and any value/object that needs to be passed into the filter. New filters can easily be added as well.

Related

MVVMCross 4.0 Xamarin Forms Page not Found

We've been using MVVMCross for the 18 months. Great Stuff. But, we're looking to migrate from Xamarin.iOS to Xamarin.Forms in an effort to speed development time.
We have a PCL with our ViewModels. But, would like to have our View (Pages) in a separate PCL library, to allow parallel development with Native application.
MVVMCross can not seem to locate the Page if it's located in a separate PCL library, OR if it's located in the Application. However, if I put the Page in the same PCL as the ViewModels, things work like a champ.
I've tried putting the following code in our Setup.cs
protected override IEnumerable<Assembly> GetViewAssemblies()
{
var list = new List<Assembly>();
list.AddRange(base.GetViewAssemblies());
list.Add(typeof(NuSales.Forms.Pages.TestPage).GetTypeInfo().Assembly);
return list;
}
But, still no joy.
Any hints on how to fix the resolver to find the View (Page)?
Thanks
Looking at https://github.com/MvvmCross/MvvmCross-Forms/blob/master/MvvmCross.Forms.Presenter.Core/MvxFormsPageLoader.cs#L44
protected virtual Type GetPageType(string pageName)
{
return _request.ViewModelType.GetTypeInfo().Assembly.CreatableTypes()
.FirstOrDefault(t => t.Name == pageName);
}
... I'd say you need to override the default IMvxFormsPageLoader to change that single Assembly lookup.
...or (for bonus points) you could send in a Pull Request that changes the default behaviour to use the view assemblies collection - and it could also store a Dictionary to avoid multiple Reflection passes and to speed up lookup times.
Hopefully, I'm doing this right in terms of StackOverflow etiquette. Using Stuart's suggestion... A quick fix is.
Create a FormPageLoader like below.
public class MyFormsPageLoader : MvxFormsPageLoader
{
public MyFormsPageLoader() {
}
protected override Type GetPageType(string pageName)
{
return typeof(NuSales.Forms.Pages.TestPage).GetTypeInfo().Assembly.CreatableTypes().FirstOrDefault(t => t.Name == pageName);
}
}
Then you need to register it. I did it in my App.Initialize code
public class FormsApp : MvxApplication
{
public override void Initialize()
{
base.Initialize();
Mvx.RegisterSingleton(typeof(IMvxFormsPageLoader), new MyFormsPageLoader());
RegisterAppStart<TestViewModel>();
}
}

Factory to return array of IItem from single object

This is a simplified version of the problem i am solving but conceptually equivalent.
This project is using castle windsor and I am trying to keep all factories in the container.
I have a single object that represents data parsed from a text file. After parsing this file I need to write a new text file with 2 line based on data in the original object.
lets say the text file is
Some Person, Work Phone, Mobil Phone
this gets parsed into
public class Person
{
public string Name{get;set;}
public stirng WorkPhone {get;set;}
public stirng MobilPhone {get;set;}
}
Now this is a simplified example so keep that in mind please. The next step is to creat new object instances that represent each line we will write to the text file
public interface IFileEntry
{
string Name{get;set;}
string Number{get;set;}
}
public class PersonWorkPhoneEntry : IFileEntry
{
public string Name {get;set;}
public string Number{get;set;}
public override ToString(){....}
}
public class PersonMobilPhoneEntry: IFileEntry
{
public string Name{get;set;}
public string Number{get;set;}
public override ToString(){....}
}
so being that we are using Castle for this lets make a factory
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
}
I have created my own implementation for the DefaultTypedFactoryComponentSelector and install that for this factory only.
public class FileEntryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
{
if (method.Name == "Create" && arguments.length == 3)
{
return (string)arguments[0];
}
return base.GetComponentName(method, arguments);
}
}
This works,
var workEntry = _factory.Create("PersonWorkPhoneEntry", person.Name, person.WorkPhone)
var mobilEntry = _factory.Create("PersonMobilPhoneEntry", person.Name, person.WorkPhone)
//then write the tostring to a text file
Sorry for the long setup but i think its needed. What I am trying to do Is
public interface IFileEntryFactory
{
IFileEntry Create(string entryType, stirng Name, string Number
IFileEntry[] Create(Person person)
}
var entries = _factory.Create(person);
foreach(var e in entries)
///write to text file.
I have been digging all over for a solution like this with no results.
What seems to be a possible solution taking the example shown here (Castle Windsor Typed Factory Facility with generics)
Im currently working on implementing something like this now, not sure if this is the right way to solve this problem.
The questions:
are there any other ways to have the factory return the array of
needed objects
what is the best practice for solving something like
this
any examples and reading for advanced factories
It is possible to make a Factory return to you an array of objects which are already registered in the container. Here is an example
container.Register(Component.For<IMyStuffProvider>().AsFactory()) // registration
public interface IStuffProvider
{
IEnumerable<IMyStuff> GetAllStuff();
void Release(IMyStuff stuff);
}
This code makes possible that every registered implementation of IMyStuff gets returned by the factory.
But I think that your problem is different : you are using the factory for the wrong purpose. TypedFactory is to get instances of objects that are already registered in the container during app start and not to manipulate files. Their purpose is to solve problems regarding dependencies.
If you are parsing a csv/txt into objects and then writing some of the rows back into another csv/txt you have to make
IFileEntryManager (with an implementation) with a methods like DeserializeFileToObjects, WriteObjectsToFile, etc.
IFileEntryManagerFactory to create and return IFileEntryManager. ( Castle typed factory here :) )
Now inject your IFileEntryManagerFactory in your ctor of the class that needs to serialize/deserialize text files and and use it to get your FileEntryManager which in turn will act upon your text files.
If you have different objects like Person, Company, Employee... etc. and you want to handle them with generic manipulator - it is ok. The best way is to implement a Generic Repository. Lets say ICsvRepository<T>. Just search for 'Generic Rpository in c#' and ignore that fact that most of the implementation examples are with EntityFramework as a persistence store. Behind the interface you can make it read/write to csv rather than to DB.
Lets generalize it. If you have to deal with resources - files, sql, blobs, tables, message bus or whatever resource persistent/non persistent which comes in or goes out of your application you have to manipulate it through an abstraction IMyResourceManager with its corresponding manipulation methods. If you have several implementations of IMyResourceManager and you want to decide during runtime which implementation you want then you have to make IMyResourceManagerFactory with a component selector or factory method and place your differentiation logic there.
That is why I think you do not need a TypedFactory for text file read/write but a pure ITextFileManipulator which you have to register in the container and get it through constructor. You may need a typed factory if you go for ICsvRepository<T> where T is your Person class. Inside the implementation of ICsvRepository<T> you will need ICsvFileManipulator.

Windsor Castle IoC - Http Session

I am using MVC 3, I have a range of Controllers depending on various repositories, 1 of my repository relies on the http context session.
I have created interfaces for each of my repositories in order to use the Windsor-Castle IoC.
How can I pass the current session object down to the repository that needs it?
I used to be able to do this and the "Resolve" would take care passing the session to the repository that needed it, somehow I cannot do this in the latest version (2.5.3 Feb 2011):
Protected Overrides Function GetControllerInstance(ByVal requestContext As System.Web.Routing.RequestContext, _
ByVal controllerType As System.Type) As System.Web.Mvc.IController
Dim match As IController
' 1 or more components may need the session,
' adding it as a (possible) dependency
Dim deps As New Hashtable
deps.Add("session", HttpContext.Current.Session)
match = container.Resolve(controllerType, deps)
Return match
End Function
Thanks, Vincent
Look closely at your design. When you look at it functionaly, your repository doesn't really depend on the the session at all, but at some data you store in the session. Create an abstraction over the things you want to extract from the session and let the repository depend on such abstraction. For instance:
public interface IUserProvider
{
int GetCurrentUserId();
}
public class SomeRepository : ISomeRepository
{
private readonly IUserProvider userProvider;
public SomeRepository(IUserProvider userProvider)
{
this.userProvider = userProvider;
}
}
Now you can create the following implementation of that abstraction:
private class HttpSessionUserProvider : IUserProvider
{
public int GetCurrentUserId()
{
return (int)HttpContext.Current.Session["UserId"];
}
}
You can register this concrete type in your IoC configuration.
This is much better, because you don't want to let your repository depend directly on the HTTP session. This makes testing harder and creates a dependency between your repository and a specific presentation technology.
The controller factory's sole responsibility is to create controllers. Not handling sessions or any other dependencies. It's best to just register the session as a separate component and let Windsor autowire it. Remove the 'deps' Hashtable from there and register:
container.Register(Component.For<HttpSessionStateBase>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)));
Then inject HttpSessionStateBase in your controller.
BTW: controllers already have access to the session, there is no need to do this if you're just injecting the session to controllers.

Repository without ORM for saving object graph

I know it's fairly straight forward to create Repository for retreiving domain models without ORM (Repository Pattern without LINQ or other ORM?). However, what about saving domain models and its internal object graph?
public class Car: IAggregateRoot, IEntity, ICar
{
public IEnumerable<IWheel> Wheels {get; set;}
}
public class CarRepository
{
public void Save(ICar car)
{
// calls Dao
// update/insert all wheels as required
// update/insert car as required
}
}
Here we need to take about change tracking etc. How does one go about to implement it?
For my specific implementation I'm treating Linq to Sql as Dao. Linq to sql does change tracking but the domain models that I created are not. They are straight POCO and not mapped directly by linq to sql. Everything is done by a custom DataMapper
public class CarDataMapper : IMapper<LinqData.Car, Domain.ICar>
{
public ICar Map(LinqData.Car linqCar)
{
ICar = new Car () { Wheels = linqCar.Wheels.Select( w => new WheelDataMapper().Map(w));
}
}
Is there any straight forward way to implement Repository to save object graph without exposing linqToSql or NHibernate to the domain layer? Or am I missing something here?
I am too struggling to find out solution..
DDD without ORM, is it possible..
Look at http://solveme.wordpress.com/2009/11/11/ddd-without-any-orm-tool-is-it-possible/

Access to global application settings

A database application that I'm currently working on, stores all sorts of settings in the database. Most of those settings are there to customize certain business rules, but there's also some other stuff in there.
The app contains objects that specifically do a certain task, e.g., a certain complicated calculation. Those non-UI objects are unit-tested, but also need access to lots of those global settings. The way we've implemented this right now, is by giving the objects properties that are filled by the Application Controller at runtime. When testing, we create the objects in the test and fill in values for testing (not from the database).
This works better, in any case much better than having all those objects need some global Settings object --- that of course effectively makes unit testing impossible :) Disadvantage can be that you sometimes need to set a dozen of properties, or that you need to let those properties 'percolate' into sub-objects.
So the general question is: how do you provide access to global application settings in your projects, without the need for global variables, while still being able to unit test your code? This must be a problem that's been solved 100's of times...
(Note: I'm not too much of an experienced programmer, as you'll have noticed; but I love to learn! And of course, I've already done research into this topic, but I'm really looking for some first-hand experiences)
You could use Martin Fowlers ServiceLocator pattern. In php it could look like this:
class ServiceLocator {
private static $soleInstance;
private $globalSettings;
public static function load($locator) {
self::$soleInstance = $locator;
}
public static function globalSettings() {
if (!isset(self::$soleInstance->globalSettings)) {
self::$soleInstance->setGlobalSettings(new GlobalSettings());
}
return self::$soleInstance->globalSettings;
}
}
Your production code then initializes the service locator like this:
ServiceLocator::load(new ServiceLocator());
In your test-code, you insert your mock-settings like this:
ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);
It's a repository for singletons that can be exchanged for testing purposes.
I like to model my configuration access off of the Service Locator pattern. This gives me a single point to get any configuration value that I need and by putting it outside the application in a separate library, it allows reuse and testability. Here is some sample code, I am not sure what language you are using, but I wrote it in C#.
First I create a generic class that will models my ConfigurationItem.
public class ConfigurationItem<T>
{
private T item;
public ConfigurationItem(T item)
{
this.item = item;
}
public T GetValue()
{
return item;
}
}
Then I create a class that exposes public static readonly variables for the configuration item. Here I am just reading the ConnectionStringSettings from a config file, which is just xml. Of course for more items, you can read the values from any source.
public class ConfigurationItems
{
public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());
private static ConnectionStringSettings RetrieveConnectionString()
{
// In .Net, we store our connection string in the application/web config file.
// We can access those values through the ConfigurationManager class.
return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
}
}
Then when I need a ConfigurationItem for use, I call it like this:
ConfigurationItems.ConnectionSettings.GetValue();
And it will return me a type safe value, which I can then cache or do whatever I want with.
Here's a sample test:
[TestFixture]
public class ConfigurationItemsTest
{
[Test]
public void ShouldBeAbleToAccessConnectionStringSettings()
{
ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
Assert.IsNotNull(item);
}
}
Hope this helps.
Usually this is handled by an ini file or XML configuration file. Then you just have a class that reads the setting when neeed.
.NET has this built in with the ConfigurationManager classes, but it's quite easy to implement, just read text files, or load XML into DOM or parse them by hand in code.
Having config files in the database is ok, but it does tie you to the database, and creates an extra dependancy for your app that ini/xml files solve.
I did this:
public class MySettings
{
public static double Setting1
{ get { return SettingsCache.Instance.GetDouble("Setting1"); } }
public static string Setting2
{ get { return SettingsCache.Instance.GetString("Setting2"); } }
}
I put this in a separate infrastructure module to remove any issues with circular dependencies.
Doing this I am not tied to any specific configuration method, and have no strings running havoc in my applications code.