I have a Class called Repository for accessing (Read/Write to and from) Database.
The projects that require access to the database create an object of Repository and pass the connection string as a constructor parameter for the repository to work for that particular project.
I have few methods in the Repository that i want to be available only if certain connection strings are passed. I don't want them to be available if some different connection string is passed.
Is there any way I can accomplish that?
I have never used method header technique, can that help? if yes, how can i use it? if no, please let me know if there is any other way to achieve my goal.
Regards.
You could use a factory method pattern to accomplish your goal.
Create a RepositoryFactory class that takes in the connection string and returns a different repository based upon the contents of the string.
public class RepositoryFactory {
public IRepository GetRepository(string connection)
{
if(SomeTestOnConnect(connection))
return new SimpleRepository(connection);
else
return new FullRepository(connection);
}
}
With this when someone wants a repository they call the GetRepository method.
Sort of doing:
if (_connection == "XYZ")
throw new InvalidOperationException();
Is it possible that you could refactor your approach to create a new class:
public class ConnectionInfo
{
public string ConnectionString { get; set; }
public bool IsLimitedAccess { get; set; }
}
Then, in each repository method not allowed, if limited access, return null or throw exception or something?
If you know in advance whether you'll need the extra methods, you could have a base version which doesn't support the extra methods, and a derived type which does. The constructor for the derived type could throw an exception if required information is not provided.
Using a factory method instead of a constructor would allow a base or fancy object to be constructed based upon the passed-in connection string; if you just have one factory method, though, you'll have to typecast the result if you want to use the extra methods.
The best approach may be to have a factory method for each defined type, with a guarantee that it will either return an object that's at least as good as the requested type or throw an exception if it can't. This approach would allow for future expansion in case more further-derived types become available.
If you want to limit the available methods, you could use a pattern like this.
Use the factory to get an instance like this:
var repo = RepositoryFactory.Resovle<IFullRepository>("connection string");
And the code that makes this work is here
public class RepositoryFactory
{
public static T Resovle<T>(string connection) where T: IRepository
{
IRepository instance = new Repository(connection);
return (T)instance;
}
private class Repository : IFullRepository
{
private string _connection;
public Repository(string connection)
{
_connection = connection;
}
public object Get(int id)
{
// select
}
public void Save(object o)
{
// upate
}
public void Create(object o)
{
// create
}
public void CustomMethodOne()
{
// do something specialized
}
public void CustomMethodTwo()
{
// do something specialized
}
}
}
public interface IRepository
{
object Get(int id);
void Save(object o);
void Create(object o);
}
public interface IRepositoryProjectOne: IRepository
{
void CustomMethodOne();
}
public interface IRepositoryProjectTwo: IRepository
{
void CustomMethodTwo();
}
public interface IFullRepository: IRepositoryProjectOne, IRepositoryProjectTwo
{
}
The downsides are, you get an explosion of Interfaces to control what methods are exposed. However, it is possible to cast between the various interfaces, but it avoids having to throw exceptions when a method isn't implemented.
There doesn't seem to be a perfect way to do this however I think your calling method needs to know whether or not it is allowed to write to the Repository as another poster has stated the availability of methods is something that needs to be known at compile time rather than run time.
The solution would be to create two interfaces, one that offers full functionality and one that offers limited functionality.
public interface IRepository : IRead
{
void Write(object o);
}
public interface IRead
{
object Read();
}
Your Repository object then implements the top interface.
public class Repository : IRepository
{
private readonly string _connectionString;
public Repository(string connectionString)
{
_connectionString = connectionString;
}
public object Read()
{
// Do stuff
}
public void Write(object o)
{
// Do stuff
}
}
You can then have a class that determines if the connection string demands a read only repository or not and exposes 2 different methods to return the given type of interface (meaning you need to know the type at compile time).
public static class RepositoryFactory
{
public static bool ConnectionStringIsReadOnly(string connectionString)
{
return connectionString.Contains("user=hacker");
}
public static IRead GetReadOnlyRepository(string connectionString)
{
return new Repository(connectionString);
}
public static IRepository GetRepository(string connectionString)
{
if (ConnectionStringIsReadOnly(connectionString)) throw new ArgumentException(#"Given connectionString is not allowed full repository access", "connectionString");
return new Repository(connectionString);
}
}
You can then consume this as follows, seperating the points where you try to do actions that require full access by checking that you have a version of IRepository or of IRead only.
public class Program
{
public void ConsumeRepository(string connectionString)
{
IRead reader = null;
IRepository repository = null;
if (RepositoryFactory.ConnectionStringIsReadOnly(connectionString))
reader = RepositoryFactory.GetReadOnlyRepository(connectionString);
else
{
repository = RepositoryFactory.GetRepository(connectionString);
reader = repository;
}
object o = reader.Read();
// do something with o
// if allowed then write o to repository
if (repository != null)
{
repository.Write(o);
}
}
}
Related
I'am developing a small system and i developed the classic generic repository. For now, i have the following architecture for my DAL.
public interface IRepositorio<T> where T : class
{
T Get(long id);
long Insert(T obj);
bool Update(T obj);
bool Delete(T obj);
}
public abstract class Repositorio<T> : IRepositorio<T> where T : class
{
public IDbConnection Connection
{
get
{
return new SqlConnection(ConfigurationManager.ConnectionStrings["DBFila"].ConnectionString);
}
}
public T Get(long id)
{
//...
}
public long Insert(T obj)
{
//...
}
public bool Update(T obj)
{
//...
}
public bool Delete(T obj)
{
//...
}
}
My concrete repository looks like this:
public class FilaRepositorio : Repositorio<FilaRepositorio>
{
public FilaRepositorio()
{
}
public void SomeCustomMethod()
{
// Some custom method
}
}
I am also using Simple Injector to follow the IoC and DI patterns, for this reason, when i try to call "SomeCustomMethod()" i dont have access to it (obviously). Look:
public class Processador
{
private IRepositorio<FilaModel> _repoFila;
public Processador(IRepositorio<FilaModel> repoFila)
{
_repoFila = repoFila;
}
public void Processar()
{
_repoFila.SomeCustomMethod(); // <-- wrong
((FilaRepositorio)_repoFila).SomeCustomMethod();// <-- works
}
}
Given this i have some questions:
Is a good or acceptable practice to make that cast (FilaRepositorio)?
If its not a good practice, how to write good code for this case?
There are a few options available. The main problem with making the cast is that it is an implementation concern.
What would happen if the injected object was not a FilaRepositorio?
By making the cast you are tightly coupling the class to an implementation concern that is not guaranteed to be the inject dependency. Thus the constructor is not being entirely truthful about what it needs to perform its function.
This demonstrates the need to practice Explicit Dependencies Principle
The Explicit Dependencies Principle states:
Methods and classes should explicitly require (typically through
method parameters or constructor parameters) any collaborating objects
they need in order to function correctly.
One way to avoid it would be to make a derived interface that explicitly exposes the desired functionality of its dependents.
public interface IFilaRepositorio : IRepositorio<FilaModel> {
void SomeCustomMethod();
}
public class FilaRepositorio : Repositorio<FilaModel>, IFilaRepositorio {
public void SomeCustomMethod() {
//...other code removed for brevity.
}
}
and have the Processador depend on that more targeted abstraction.
Now there is no need for the cast at all and the class explicitly expresses what it needs.
public class Processador {
private readonly IFilaRepositorio _repoFila;
public Processador(IFilaRepositorio repoFila) {
_repoFila = repoFila;
}
public void Processar() {
_repoFila.SomeCustomMethod(); // <-- works
}
}
If you need to access a specific method from any part of your application, then that specific method must be part of your abstraction, or else there is no guarantee that you may use it when changing the concrete class.
I do not believe that your use of casting is a good idea at all, what is usually done in this case is to create a specific interface which defines any other method you could need to use:
public interface IFilaRepositorio : IRepositorio<Fila>
{
void SomeCustomMethod();
}
And than use and declare that specific interface in any part of your code where you believe you need to use it:
public class Processador
{
private IFilaRepositorio _repoFila;
public Processador(IFilaRepositorio repoFila)
{
_repoFila = repoFila;
}
public void Processar()
{
_repoFila.SomeCustomMethod();
}
}
All examples which I found in general base on enumeration which provides to return the proper class. I need something which reacts in general on type of class and also is controlling constructors of new object by giving to it new parameters with each call.
Is it still factory method? Is it good solution? Can I play with design patterns in such way? Maybe there is better solution to provide?
using System;
namespace ConsoleApplication1
{
public abstract class Strategy
{
protected int Init;
private static int _initA = 3;
private static int _initB = 42;
public static Strategy StrategyFactory(Strategy strategyType)
{
var tempStrategyA = strategyType as StrategyA;
if (tempStrategyA != null)
{
_initA++;
return new StrategyA(_initA);
}
var tempStrategyB = strategyType as StrategyB;
if (tempStrategyB != null)
{
_initB = _initA * 2;
return new StrategyB(_initB);
}
throw new ArgumentException();
}
}
public class StrategyA : Strategy
{
public StrategyA(int init)
{
Init = init*2;
}
}
public class StrategyB : Strategy
{
public StrategyB(int init)
{
Init = init*3;
}
}
}
To me what it looks like is you actually want to have a different factory for each strategy. Factories are good if you want to either manage the lifetime of the objects the factory creates, or to manage dependencies / arguments for the construction of the various types.
Definition of strategy factories
interface IStrategyFactory
{
public Strategy Create(int value);
}
class StrategyAFactory : IStrategyFactory
{
public Strategy Create(int value)
{
return new StrategyA(value);
}
}
class StrategyBFactory : IStrategyFactory
{
public Strategy Create(int value)
{
return new StrategyB(value);
}
}
Usage
class MyController : ApiController
{
private IStrategyFactory _factory;
public MyController(IStrategyFactory factory)
{
_factory = factory;
}
public HttpResponseMessage Get(int value)
{
// here we don't care what exact strategy is used, this is good!
var strategy = _factory.Create(value);
var newValue = strategy.Calculate();
return new HttpResponseMessage(newValue);
}
}
This is a very strange factory method. See your factory method signature:
// "strategyType"? It's not a type, but an object reference
public static Strategy StrategyFactory(Strategy strategyType)
In .NET there's a class called Type which represents type metadata for some given type. You get it using typeof operator or Object.GetType() method.
Your factory method should be:
public static Strategy StrategyFactory(Type strategyType)
And you can instantiate a type using reflection:
Activator.CreateInstance(strategyType);
There's also a CreateInstance overload to give constructor arguments.
What about generics?
Since .NET 2.0 (we're talking about a lot of years ago!), .NET has generics. In summary, they provide a way to specify parameters which don't have a concrete type until a method or type is actually declared or used somewhere and provides which actual type will have the whole parameters.
For example, this would be a modern factory method:
// "where ..." is a generic constraint which defines that the given generic
// argument must be Strategy or a derived class of Strategy, and it must
// have a public parameterless constructor
public TStrategy Create<TStrategy>() where TStrategy : Strategy, new()
{
TStrategy strategy = new TStrategy();
// more stuff
return strategy;
}
And now you can use it this way:
MyStrategy strategy = StrategyFactory.Create<MyStrategy>();
I could give you a generics' master class, but this goes out of the scope of your question. Anyway I gave you a clue/hint about how you need to build a factory using the right tool. You can learn more about generics in MSDN.
Below is the implementation of a dependency that is injected into another class.
public class CsvDataProvider : ICsvDataProvider
{
readonly ICsvReaderFactory _factory;
public CsvDataProvider(ICsvReaderFactory factory)
{
_factory = factory;
}
public IEnumerable<TRecord> GetData<TRecord>(string filepath) where TRecord : class
{
var reader = _factory.CreateCsvReader(filepath);
return reader.GetRecords<TRecord>();
}
}
The reader that is created by the factory will read all lines in a CSV file and convert each line to an instance of TRecord. I do not own the reader code and can not change the GetRecords<TRecord>() method.
This is where I am stuck:
public class CsvDataMigrationController
{
readonly ICsvDataProvider _provider;
readonly ICsvDataMigration _migration;
public CsvDataMigrationController(ICsvDataProvider provider, ICsvDataMigration migration)
{
_provider = provider;
_migration = migration;
}
public void ProcessFile(string path)
{
var records = _provider.GetData<I_DONT_WANT_TO_EXPLICITLY_SAY>(path); //<-- Help!
_migration.Migrate(records);
}
}
The intent is to inject a data provider and a migration procedure class into CsvDataMigrationController. The controller would call the data provider to get the data and pass the data into the migration class.
I don't want the CsvDataMigrationController to know about the type of data involved.
I don't want the CsvDataProvider to know about the migration.
I don't want the CsvDataMigration to know about where the data came from.
Any advice on how I can achieve this?
Note: I did not include the CsvDataMigration class because I didn't think it was useful in the explanation, but will include it if needed.
Well, since you can't change GetRecords, then perhaps the most straightforward way is to ask the migration interface for the record type, and use reflection to call the generic GetData method with that runtime-obtained type. Something like:
public void ProcessFile(string path)
{
Type recordType = _migration.InputRecordType;
var getDataMethod =
_provider.GetType()
.GetMethod("GetData")
.MakeGenericMethod(recordType);
var records = getDataMethod.Invoke(_provider, new object[] { path });
_migration.Migrate(records);
}
Typically, you will define a non-generic alternative such as
public interface ICsvDataProvider
{
IEnumerable GetData(string filepath, Type recordType)
IEnumerable<TRecord> GetData<TRecord>(string filepath)
where TRecord : class;
}
So you could call this as
public class CsvDataMigrationController
{
private string targetTypeName = ...;
public void ProcessFile(string path)
{
var recordType = Type.GetType(this.targetTypeName);
var records = _provider.GetData(path, recordType);
_migration.Migrate(records);
}
}
In this way, the generic method is just a bit of syntactic sugar around the non-generic method.
Using reflection (as in #Cameron's answer) is another solution. In both cases you must know the target type at run time (rather than at compile time as the generic method requires).
I'm new to NHibernate and not very good at C#, but I'm learning. I have a DataProvider class which provides data for my application using NHibernate 3. It's structured pretty much identical to Steve Bohlen's Summer of NHibernate videos.
I've noticed that I'm about to repeat my code a lot and I want to simplify my DataProvider. For example I have two business classes called Instrument and Broker. The method to add an Instrument in my DataProvider is:
public int AddInstrument(Instrument instrument)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(instrument);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
and the AddBroker class looks remarkably similar (just find and replace). So I thought maybe I could use Generics to solve the problem. Something like:
public class DataProvider <TEntity>
{
public int AddEntity(TEntity entity)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(entity);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
}
With this I can pass in a Broker, an Instrument or anything and I save myself a lot of repetitive code. The problem I'm having is that in my Test class I create a new DataProvider each time a test is run like this:
#region Fields
private DataProvider _provider;
private SessionManager _sessionManager;
private NHibernate.ISession _session;
#endregion
[SetUp]
public void Setup()
{
DatabaseSetUp();
_session = _sessionManager.GetSession();
_provider = new DataProvider(_session); // problem here
}
Using generics I have to pass in the object type to my DataProvider. Can you think of a way to solve this? I am a novice programmer and I am wondering if I am going down the right path. Should I be doing something totally different?
UPDATE
I have tried to implement Groo's answer but am having some issues. Here's what I've done.
IRepo.cs
interface IRepo<T>
{
int Add<Entity>(Entity entity);
void Delete<Entity>(Entity entity);
void GetById<Entity>(int Id);
}
BaseRepo.cs
public abstract class BaseRepo <T> : IRepo <T>
{
private ISession _session;
#region SessionManagement
public BaseRepo(ISession session)
{
_session = session;
}
public ISession Session
{
set { _session = value; }
}
#endregion
public int Add<Entity>(Entity entity)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(entity);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
// other methods omitted for brevity
}
IRepoFactory.cs
interface IRepoFactory
{
IInstrumentRepo CreateInstrumentRepo(ISession s);
}
RepoFactory.cs
public class RepoFactory : IRepoFactory
{
public IInstrumentRepo CreateInstrumentRepo(ISession s) // problem here
{
return new InstrumentRepo(s);
}
}
IInstrumentRepo.cs
interface IInstrumentRepo : IRepo<Instrument>
{
}
InstrumentRepo.cs
public class InstrumentRepo : BaseRepo<Instrument>, IInstrumentRepo
{
public InstrumentRepo(ISession s) : base(s) { }
}
In RepoFactory.cs I get this error:
Inconsistent accessibility: return type 'MooDB.Data.IInstrumentRepo' is less accessible than method 'MooDB.Data.RepoFactory.CreateInstrumentRepo(NHibernate.ISession)'
Any ideas what I'm missing?
First of all, to address your Test Setup question: the term Repository might suggest that it should be a long lived, persistent object, but Repositories used in DAL operations should actually be lightweight stateless objects with short lifetimes: you instantiate one when you need it, and throw it away as soon as you're done. When you think about this is terms of performance, you can easily instantiate millions of them per second.
Combined with NHibernate's short lived Session instances, this is how your code is meant to look like when everything is in place:
using (var session = SessionManager.OpenSession())
{
// create an instrument repo
IInstrumentRepo instruments = DAL.RepoFactory.CreateInstrumentRepo(session);
var guitar = instruments.Find(i => i.Type == "Guitar");
// create a customer repo
ICustomerRepo customers = DAL.RepoFactory.CreateCustomerRepo(session);
var cust = customers.Find(c => c.Name == "Mark")
// do something -> changes will be persisted by NH when session is disposed
cust.Instruments.Add(guitar);
}
That's the general idea. Now, let me explain it in more detail:
You may have noticed that each repo has its own interface, and is created through a repo factory. Using a factory to create repositories means you can easily create mock repo factories, which will create any custom implementation of a repository for testing.
Each repo interface inherits from the base interface generic interface, IRepo<T>. This allows you to use a generic repository in 99% of cases, but still leave room to implement a custom query method specific to, say, Customer entities only:
public interface IInstrumentRepo : IRepo<Instrument>
{
// nothing to do here
}
public interface ICustomerRepo : IRepo<Customer>
{
// but we'll need a custom method here
void FindByAddress(string address);
}
public interface IRepo<T>
{
T GetById(object id);
T Save(T item);
}
This means that your repo implementations will, in most cases, simply inherit from the base abstract class (I named it BaseRepo, but it's essentially what your DataProvider class does right now):
class InstrumentRepo : BaseRepo<Instrument>, IInstrumentRepo
{
// no need to implement anything here except pass the session downwards
public InstrumentRepo(ISession s) : base(s) { }
}
Your factory will simply need to instantiate the proper repository when asked:
public class RepoFactory : IRepoFactory
{
public IInstrumentRepo CreateInstrumentRepo(ISession s)
{
return new InstumentRepo(s);
}
}
And you will need to use the Singleton pattern in a, say, DAL class to hold the factory (there are slightly better ways to do this, using DI, but for now this will do just fine):
public static class DAL
{
// repo factory is pretty lightweight, so no need for fancy
// singleton patterns
private static readonly IRepoFactory _repoFactory = new RepoFactory();
public static IRepoFactory RepoFactory
{
get { return _repoFactory; }
}
}
The answer to your question is Absolutely Yes!
This is what generics are meant for.
You are in the right way.
This argument is really too long to discuss here but you can find a lot of usefull info in this article:
http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
It helps me a lot to create my generic nhibernate Dao
Your data provider class doesn't necessarily need to be generic - you can just make the AddEntity method itself generic. Then you instantiate a DataProvider instance, and call (for example) its AddEntity<Instrument> method. Your class would look like this:
public class DataProvider
{
public int AddEntity<TEntity>(TEntity entity)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
int newId = (int)_session.Save(entity);
_session.Flush();
tx.Commit();
return newId;
}
catch (NHibernate.HibernateException)
{
tx.Rollback();
throw;
}
}
}
}
I'm implementing a factory pattern that looks as follows.
public class FeedFactory
{
#region Singleton Pattern
//..
#endregion
private static Feed[] _factory = new Feed[(int)FeedType.Total];
public void RegisterFeed(FeedType feedType,Feed feed)
{
if (_factory[(int)feedType] == null)
{
_factory[(int)feedType] = feed;
}
else
{
// already registered
}
}
public Feed GetFeed(FeedType feedType)
{
return _factory[(int)feedType];
}
}
Here, Feed is an abstract class from which the different classes inherit. How can I register the different classes? Is it possible to do it from their constructor?
This is not a factory pattern. A factory will always have some constructor logic in it, at least one new. That's the idea of a factory: the caller doesn't have to worry about how objects are created. This is a singleton repository.
So first of all, instead of using an array, you should be having a type indexed dictionary.
private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>();
After that, you don't need a register method. The dictionary should be filled automatically when you retrieve singletons.
Now I suppose your Feed class has a default constructor without arguments. In that case, you can implement a factory method directly from the abstract class Feed. We're going to use some generics here, because it allows you to control inheritance:
public abstract class Feed
{
public static T GetInstance<T>() where T:Feed, new()
{
T instance = new T();
// TODO: Implement here other initializing behaviour
return instance;
}
}
Now back to your singleton repository.
public class FeedSingletonRepository
{
private static readonly object _padlock = new object();
private static Dictionary<Type, Feed> _singletons = new Dictionary<Type, Feed>();
public static T GetFeed<T>() where T:Feed
{
lock(_padlock)
{
if (!_singletons.ContainsKey(typeof(T))
{
_singletons[typeof(T)] = Feed.GetInstance<T>();
}
return (T)_singletons[typeof(T)];
}
}
}
Note that I included a threadsafe behaviour which is a good thing to do when you work with singletons.
Now if you want to get the singleton for a given type inheriting from Feed (let's call it SpecializedFeedType), all you have to do is:
var singleton = FeedSingletonRepository.GetFeed<SpecializedFeedType>();
or
SpecializedFeedType singleton = FeedSingletonRepository.GetFeed();
which is the same line with a slightly different syntax.
Edit2: changed some syntax errors.
Just as a side note -- as a factory is intended to wrap creation, it's a curious choice that you're creating objects and registering them with the factory. Is this more an object repository than a factory, or is there more to the class than I'm seeing?
If it is an object repository, then you might also find some extra inspiration in other questions, like this one.
When you call the RegisterFeed method you need to pass a concrete instance of a Feed class. So it is the responsibility of the caller to provide the concrete implementation.
Just register the type of the classes you want to create, then use Activator.CreateInstance to create instances of that type.
It should work this way:
private static Type[] _factory = new Type[(int)FeedType.Total];
public void RegisterFeed(FeedType feedType, Type type)
{
...
_factory[(int)feedType] = type;
...
}
public Feed GetFeed(FeedType feedType)
{
return Activator.CreateInstance(_factory[(int)feedType]) as Feed;
}
You can call RegisterFeed like the following:
RegisterFeed(FeedType.SomethingSpecial, typeof(MyDerivedSpecialFeed));
class FeedFactory {
public IFeedFactory GetFeedFactory(string type) {
switch(type) {
case "1": return new Feed1(); break;
case "2": return new Feed2(); break;
}
}
}
Note all Feeds Must implement an IFeedFactory interface and implement the method necessary.
//From the client
FeedFactory ff1 = new FeedFactory();
IFeedFactory obj = ff1.GetFeedFactory("1");
obj.ExecuteMethod();