I have three database operations like so:
public void Add<T>(T entity)
{
using (var transaction = Session.BeginTransaction())
{
if (entity is IEnumerable)
{
foreach (var item in (IEnumerable) entity)
{
Session.Save(item);
}
}
else
{
Session.Save(entity);
}
transaction.Commit();
}
}
public void Update<T>(T entity)
{
using (var transaction = Session.BeginTransaction())
{
if (entity is IEnumerable)
{
foreach (var item in (IEnumerable) entity)
{
Session.Update(item);
}
}
else
{
Session.Update(entity);
}
transaction.Commit();
}
}
public void Delete<T>(T entity)
{
using (var transaction = Session.BeginTransaction())
{
if (entity is IEnumerable)
{
开发者_JS百科 foreach (var item in (IEnumerable)entity)
{
Session.Delete(item);
}
}
else
{
Session.Delete(entity);
}
transaction.Commit();
}
}
As you can see, the only thing that differs is the Session.[something]
part. How would I refactor this into only one method?
Delegates look like a good solution here, as explained by other answerers. One other possible refactoring that could arguably simplify the inside logic would be a function that returns an IEnumerable. If the passed-in object is an IEnumerable, just return it; otherwise build a single-element enumeration with the passed-in object and return the enumeration. This would turn this:
if (entity is IEnumerable)
{
foreach (var item in (IEnumerable) entity)
{
Session.Save(item);
}
}
else
{
Session.Save(entity);
}
into this:
foreach (var item in ForceEnumerable(entity))
{
Session.Save(item);
}
You can make one method, and have it accept a delegate as a parameter, that specifies the action you want to do.
private void DatabaseAction<T>(T entity, Action<T> action)
{
using (var transaction = Session.BeginTransaction())
{
if (entity is IEnumerable)
{
foreach (var item in (IEnumerable) entity)
{
action(item);
}
}
else
{
action(item);
}
transaction.Commit();
}
}
Then refactor your 3 methods to:
public void Add<T>(T entity)
{
DatabaseAction(entity, item => Session.Save(item));
}
public void Update<T>(T entity)
{
DatabaseAction(entity, item => Session.Update(item));
}
public void Delete<T>(T entity)
{
DatabaseAction(entity, item => Session.Delete(item));
}
You could pass in an Action<T> that should be performed for the entity:
public static void DoInTransaction<T>(this T entity, Action<T> action)
{
using (var transaction = Session.BeginTransaction())
{
if (entity is IEnumerable<T>)
{
foreach (T item in (IEnumerable<T>) entity)
{
action(item);
}
}
else
{
action(entity);
}
transaction.Commit();
}
}
Example:
entity.DoInTransaction(Session.Save);
entity.DoInTransaction(Session.Update);
entity.DoInTransaction(Session.Delete);
精彩评论