I need some suggestions on how to build a fluent interface acting as a Builder, responsible for returning different concrete types depending on the methods called.
Imagine that I need to create one of the following types using my ProductBuilder (fluently): Product, ServiceProduct, PackagedProduct (both derived from Product).
I'm thinking of using a fluent syntax like this (other suggestions are more than welcome):
To create a Product:
var product = new ProductBuilder()
.Create("Simple product")
.WithPrice(12.5)
To create a ServiceProduct
var product = new ProductBuilder()
.Create("Service product")
.WithPrice(12.5)
.AsServiceProduct()
.ServiceProductSpecificMethods...()
And PackagedProduct with a call to AsPackagedProduct() instead of AsServiceProduct() etc. You get the idea.
I haven't found a sample that shows best practices on this. Only samples where the final build returns the same type.
Any suggestions?
I see two options here.
If there are a finite number of products that are fixed, and not designed to be extended, then just create a Create method for each product:
var product = new ProductBuilder()
.CreateSimple()
.WithPrice(12.5);
var product = new ProductBuilder()
.CreateService()
.WithPrice(12.5)
.ServiceProductSpecificMethods...();
If you don't want (or can't have) ProductBuilder to know all of the types of products, then I would use generics:
public class Product {}
public class SimpleProduct : Product {}
public class ServiceProduct : Product {}
var product = new ProductBuilder<SimpleProduct>()
.WithPrice(12.5);
Here's a starting place for the design to follow:
public class Product
{
public decimal Price { get; set; }
}
public class SimpleProduct : Product { }
public class ServiceProduct : Product
{
public string Service { get; set; }
}
public class ProductBuilder<T> where T : Product, new()
{
private List<Action<T>> actions = new List<Action<T>>();
public T Build()
{
T product = new T();
foreach (var action in actions)
{
action(product);
}
return product;
}
public void Configure(Action<T> action)
{
actions.Add(action);
}
}
public static class ProductExtensions
{
public static ProductBuilder<T> WithPrice<T>(this ProductBuilder<T> builder, decimal price)
where T : Product
{
builder.Configure(product => product.Price = price);
return builder;
}
public static ProductBuilder<T> WithService<T>(this ProductBuilder<T> builder, string service)
where T : ServiceProduct
{
builder.Configure(product => product.Service = service);
return builder;
}
}
If I got you correctly I would use generics here so I can write something like:
var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
.ServiceProductSpecificMethods...()
You may also add Build method before calling specific service methods so it will actually create final product:
var product = new ProductBuilder()
.Create<Serviceproduct>()
.WithPrice(12.5)
.Build()
.ServiceProductSpecificMethods...()
Related
I have a database that has multiple tables that are objects in my application, Member, Employer, Invoice etc.
I want to create a generic method that will allow me to retrieve a single object from any of the tables. ex. public Object GetRow(ClassType type, ClassKey key, object valueToFind)
so the Member method right now would be
Member member = _manager.Members.Where(m => m.MemberKey == valueToFind).FirstOrDefauilt();
Employer employer = _manager.Employers.Where(e => e.EmployerKey == valueToFind).FirstOrDefault();
Invoice invoice = _manager.Invoices.Where(i => i.InvoiceKey == valueToFind).FirstOrDefault();
How do i write a generic method that would handle all 3 cases?
I am assuming you are using entity framework. In such case you can write a method like:
public T RetrieveFirst<T>( Expression<Func<T, bool>> filter)
{
return _manager.Set<T>().FirstOrDefault(filter);
}
You can then use it as follows:
var member = RetrieveFirst<Member>(m => m. MemberKey = valueToFind );
If you wanted to unify the filtering, the entities would all have to implement an interface and have the same name of the key property.
I think #ajawad987 has written the perfect answer for you :-)
You could implement an interface that all your entities (employee, manager, etc.) inherit and then implement a generic method that works with that interface.
Basically you define a simple interface that defines the common Key property:
public interface IHasKeyProperty
{
int Key { get; set; }
}
public class Manager : IHasKeyProperty
{
public int Key { get; set; }
// Rest of manager code...
}
public class Employee : IHasKeyProperty
{
public int Key { get; set; }
// Rest of employee code...
}
And then you can write a generic query like this:
public TEntity GetByKey<TEntity>(int key)
where TEntity : IHasKeyProperty, class
{
return this._dbContext.Set<TEntity>().FirstOrDefault(x => x.Key == key);
}
I'm assuming you're using Entity Framework Core, hence the _dbContext variable in my snippet above.
Using the method would look like this:
var myEmployee = GetByKey<Employee>(207);
var myManager = GetByKey<Manager>(101);
To extend #ajawad987's answer, if you need to support different key types you could do:
public interface IHasKeyProperty<TId>
{
TId Key { get; set; }
}
public class Manager : IHasKeyProperty<int>
{
public int Key { get; set; }
// Rest of manager code...
}
public class Employee : IHasKeyProperty<Guid>
{
public Guid Key { get; set; }
// Rest of employee code...
}
public TEntity GetByKey<TEntity, TId>(TId key) where TEntity : IHasKeyProperty<TId>
{
return this._dbContext.Set<TEntity>().FirstOrDefault(x => x.Id == key);
}
I'm not sure if this question has come up before but I certainly haven't found an answer to it yet so here I am asking the community.
I have a third party library that has an abstract class (lets say A) which implements IXinterface
public abstract class A : IXinterface{
}
This class is then derived by a number of child classes, Each one of these classes have properties such Product
public class B : A {
public Product Product {get; set; }
}
public class C : A {
public Product Product {get; set; }
}
my issue is this.
I would like to create a generic method that such as this:
public List<PriceModel> GetPriceModelList(List<PriceModel> priceModelList, List<T> resultsList) where T : class
{
priceModelList.AddRange(from result in resultsList
from item in result.Product.Price
select new PriceModel
{
Price = item.price
});
return priceModelList;
}
I want to be able to do something like this
GetPriceModelList(new List<PriceModel>(), new List<B>());
GetPriceModelList(new List<PriceModel>(), new List<C>());
OR
change method signiture to accept T
GetPriceModelList<B>(new List<PriceModel>(), resultsList);
GetPriceModelList<C>(new List<PriceModel>(), resultsList);
obviously because I do not have a common concrete class or interface I can not explicitly state the type T and the abstract class does not have accessor methods to the derived classes properties. Therefore when result is fetched from the List of type T Product is not available.
Is there a way around this issue
You could cut out the intermediary, and directly operate on sequences of products.
public List<PriceModel> GetPriceModelList(
List<PriceModel> priceModelList,
IEnumerable<Product> products)
{
priceModelList.AddRange(from result in products
from item in result.Product.Price
select new PriceModel
{
Price = item.price
});
return priceModelList;
}
That would mean you'd have to provide the mechanism for getting each product at the call site.
GetPriceModelList(new List<PriceModel>(), new List<B>().Select(b => b.Product));
GetPriceModelList(new List<PriceModel>(), new List<C>().Select(c => c.Product));
Can you explain the from item in result.Product.Price line?
For me it looks like you just want:
priceModelList.AddRange(from result in resultsList
select new PriceModel
{
Price = result.Product.Price
});
To do that, you can just replace it with:
priceModelList.AddRange(from result in new List<dynamic>(resultsList)
select new PriceModel
{
Price = result.Product.Price
});
Then you can even call it in this way:
GetPriceModelList(new List<PriceModel>(),
new List<A>
{
new B { Product = new Product() },
new C { Product = new Product() }
});
But it is also a good idea to guard yourself by checking if T is actually of type B or C.
I have a class that contains a list of parameters. For example:
public class Container
{
public List<Parameter> Parameters { get; set; }
}
public class Parameter
{
puplic string Name {get; set;}
}
Class Сontainer obtained from the database through Entity Framework. Many classes contain Container. I need to ensure that all classes that contain Сontainer and also retrieved from the database containing the sorted list of Parameters. That is, the Container must sort Parameters or request step or immediately thereafter.
How this can be achieved?
Maybe write to the configuration
internal class ContainerConfiguration : EntityTypeConfiguration<Container>
{
public ContainerConfiguration()
{
ToTable("Container");
HasKey(p => p.Id);
... ???
}
}
Or wright in dataSet
protected override IQueryable<Container> DataSet(DbContext db)
{
return db.Set<ProcessMeasurer>()
.Include(it => it.Parameters.Select(p => p.Parameter));
}
Another option for solving the problem:
Create your attribute and specify which field to use for sorting by default:
public class DefaultOrderFieldAttribute : Attribute
{
public DefaultOrderFieldAttribute()
{
}
public string FieldName { get; set; }
}
[DefaultOrderField(FieldName = "ParameterName")]
public partial class Parameter
{
}
Write a Visitor, which in the case of detection of our attribute modifies select:
public class DefaultOrderVisitor : DefaultExpressionVisitor
{
public override DbExpression Visit(DbScanExpression expression)
{
const string NAMESPACE = "OrderTest";
var type =
Assembly.GetExecutingAssembly().GetType(string.Format("{0}.{1}", NAMESPACE, expression.Target.Name));
var attribute =
type.GetCustomAttributes(typeof (DefaultOrderFieldAttribute)).SingleOrDefault() as
DefaultOrderFieldAttribute;
if (attribute != null)
return expression.OrderBy(ex => ex.Property(attribute.FieldName));
return expression;
}
}
Put in our Visitor Interceptor:
public class DefaultOrderInterceptor : IDbCommandTreeInterceptor
{
public void TreeCreated(DbCommandTreeInterceptionContext interceptionContext)
{
if (interceptionContext.OriginalResult.DataSpace == DataSpace.SSpace)
{
var queryCommand = interceptionContext.Result as DbQueryCommandTree;
if (queryCommand != null)
{
var newQuery = queryCommand.Query.Accept(new DefaultOrderVisitor());
interceptionContext.Result = new DbQueryCommandTree(queryCommand.MetadataWorkspace,
queryCommand.DataSpace, newQuery);
}
}
}
}
and register it in the configuration (this class just has to be in the same assembly as the model):
public class EntityFrameworkConfiguration : DbConfiguration
{
public EntityFrameworkConfiguration()
{
AddInterceptor(new DefaultOrderInterceptor());
}
}
Need to work with the entity class.
If we want to sort the collection was in all the elements that comprise it, we have to change the appropriate property.
Obvious variant - creating property setter.
private List<Parameter> _parameters;
public List<Parameter> Parameters
{
get { return _parameters; }
set { _parameters = value.OrderBy(...).ToList();
}
But the behavior of the compiler (call the setter once, and the multiple callin to the getter) gave me a reason to assume that the target collection is not put in a property all at once. The items in the query is gradually added to the collection. Therefore, sorting in setter does not always work.
Therefore, we must carry out sorting the return value
get
{
if(_parameters == null) return null;
_parameters = _parameters.OrderBy(...).ToList();
return _parameters;
}
It works. But the problem is that an appeal to the getter, and hence sorting, will be carried out when EntityFramework inserts each value. This affects the performance.
The best variant that I know at the moment is to inherit all entities from the interface with the function Prepare
public interface IEntity
{
void Prepare();
}
and implement it in each class model. Models that comprise other models cause a method to prepare, for each desired properties.
public class SomeModel : IEntity
{
public CustomType SomeProperty { get; set; }
public OneMoreCustomType AnotherProrerty { get; set; }
public void Prepare()
{
SomeProperty.Prepare();
AnotherProperty.Prepare();
}
}
For the respective classes it will take appropriate action. Including sorting.
Сall a method to prepare the Сontainer (in this case) you before using.
For example, in the Business Logic (MVPVM).
I´m trying to buld a class factory like that:
public class Toyota() {};
public class Bmw() {};
public class Mercedes() {};
public class BrandFactory
{
private Dictionary<string, object> _Brands = new Dictionary<string, object> {
{"Toyota", Toyota},
{"Bmw", Bmw},
{"Mercedes", Mercedes}
}
public object GetBrand(string brandName)
{
return = BusinessManagers[brandName].Invoke;
}
}
This is the idea, but it´s not working - I can´t even compile the above code as the Dictionary cannot associate an 'object' with the function. I tried Func<> as well, but in that case it requires a previous type.
So, here are my questions:
Is that a correct way to implement this 'pseudo factory' ? The code came from the example at example code
If so, what needs to be fixed in the above code ?
The reason I´m asking that is because I need to create a new object based on a string that is received from a cliente application using Ajax. Like:
AjaxCall -> String Containing Object Name -> Object Inoke -> Method Call -> Send result back to client
The Method Call is a standard for all implementation of Brand.
Please can someone help me with that ?
Thanks.
You have a several options here. If you end up using a Dictionary, I recommend making it case-insensitive and taking care to avoid KeyNotFoundExceptions.
public class CaseInsensitiveStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
return string.Compare(x, y, ignoreCase: true);
}
}
The first option is to use Dictionary<string, Func<object>>.
private IDictionary<string, Func<object>> _Brands
= new Dictionary<string, Func<object>> (new CaseInsensitiveStringComparer())
{
{"Toyota", () => new Toyota() },
{"BMW", () => new Bmw() },
{"Mercedes", () => Mercedes() }
};
public object GetBrand(string brandName)
{
Func<object> func;
return _Brands.TryGetValue(brandName, out func)
? func() // invoking the delegate creates the instance of the brand object
: null; // brandName was not in the dictionary
}
Second option is to use Activator. You can use a Dictionary<string,Type>, but it may not be necessary if your type name matches the string (see notes below).
public object GetBrand(string brandName)
{
Type type;
return _Brands.TryGetValue(brandName, out type)
? Activator.CreateInstance(type) // activator invokes a parameterless constructor
: null; // brandName was not in the dictionary
}
// vs.
return Activator.CreateInstance(null, brandName).Unwrap();
// Case sensitivity would be an issue here.
// Security could be an issue here.
// Creating objects based directly off of user input means any class
// from any referenced assembly could be created if a hacker can learn
// out the namespaces and class names.
Third option is to use an IoC container to do the resolution. This gives you some flexibility with lifetime management.
The second approach currently assumes a parameterless constructor, wherease the first and third would allow for disparate constructor signatures.
In all cases, the result is simply object, which gives this approach limited utility. If all of these "brand" classes could share a common interface, then you could use IBrand or whatever in your Dictionary and as the return type.
I'm checking for bad data (values not in the Dictionary) and returning null; you could choose to throw an Exception if that makes more sense for your use case.*
You do not need a Dictionary at all:
public class DynamicFactory<T>
{
public static T Create(string className)
{
Type t = typeof(T);
return (T)Activator.CreateInstance(
t.Assembly.FullName,
t.Namespace + "." + className
).Unwrap();
}
}
namespace Brands
{
public class CarBrand { }
// The brands should be in the same namespace and assembly with CarBrand
// and should inherit from CarBrand
public class Toyota : CarBrand { };
public class Bmw : CarBrand { };
public class Mercedes : CarBrand { };
public class Titanic { } // this one is not CarBrand
class BrandFactory: DynamicFactory<CarBrand> { }
// Below are unit tests using NUnit
namespace BrandFactorySpecification
{
static class Create
{
[TestCase("Toyota", Result = typeof(Toyota))]
[TestCase("Bmw", Result = typeof(Bmw))]
[TestCase("Mercedes", Result = typeof(Mercedes))]
[TestCase("Titanic", ExpectedException = typeof(InvalidCastException))]
[TestCase("unknown", ExpectedException = typeof(TypeLoadException))]
[TestCase("String", ExpectedException = typeof(TypeLoadException))]
[TestCase("System.String", ExpectedException = typeof(TypeLoadException))]
[TestCase("ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
[TestCase("AnotherNamespace.ACarBrandFromAnotherNamespace",
ExpectedException = typeof(TypeLoadException))]
//
public static Type ShouldReturnCorrectType(string brandName)
{
return BrandFactory.Create(brandName).GetType();
}
[Test]
public static void ForTitanic()
{
DynamicFactory<Titanic>.Create("Titanic")
.ShouldBeType(typeof(Titanic));
}
}
namespace AnotherNamespace
{
public class ACarBrandFromAnotherNamespace : CarBrand { };
}
}
}
Update: the code was improved in the following ways:
The security problem, mentioned in the comments was fixed
flexibility improved
A new generic class DynamicFactory<T> now can be reused elsewhere
Brands can be located in other namespace and assembly then BrandFactory
Unit tests were added to serve as examples of usage and specification (using NUnit required for them)
That's not at all how a factory works. First of all you need a superclass that can be the parent of your car models:
public class CarModel() {};
public class Toyota() : CarModel {};
public class Bmw() : CarModel {};
public class Mercedes() : CarModel {};
Now you can create a factory that returns the correct model:
public class BrandFactory
{
public T GetBrand<T>() where T : CarModel
{
return new T();
}
}
Now when you want to create a object its is simple:
var factory = new BrandFactory();
var bmw = factory.GetBrand<Bmw>();
I'm working with an existing EF data model that includes subclassed objects. That works fine when working with individual objects, but is quite slow when loading a large number of objects for analysis.
I started exploring Dapper as an alternative for populating POCO objects used for read-only analysis.
The trouble is, I can't see any means to correctly handle an object hierarchy.
If I have
class MyBase
{
}
class MyDerived1 : MyBase
{
}
class MyDerived2 : MyBase
{
}
Dapper correctly populates a list of MyBase
var mine = conn.Query<MyBase>("SELECT * from MyTable");
The Multimap capability doesn't seem to solve the problem (or am I missing something?).
Is there a way to solve this, short of making one round-trip to the database for each subclass?
public class MyBase
{
public String BaseProp { get; set; }
}
public class MyDerived1 : MyBase
{
public String Derived1Prop { get; set; }
}
public class MyDerived2 : MyBase
{
public String Derived2Prop { get; set; }
}
Multimapping or a dynamic mapping should do the trick.
MM:
String query = "SELECT * FROM Table";
var res = conn.Query<MyBase, MyDerived1, MyDerived2, Tuple<MyBase, MyDerived1, MyDerived2>>(query, (b, d1, d2) => Tuple.Create(b, d1, d2), splitOn: "Derived1Id,Derived2Id");
The dynamic mapping is also very cool and probably more flexible in your case (Thanks #Sam!)
var res = conn.Query<dynamic>(query).Select(x => new Tuple<MyBase, MyDerived1, MyDerived2>(new MyBase() { BaseProp = x.BaseProp },
new MyDerived1() { Derived1Prop = x.Derived1Prop },
new MyDerived2() { Derived2Prop = x.Derived2Prop }));