I have the following:
public abstract class FooBase
{
public virtual int Id { get; set; }
}
public class Foo1 : FooBase { /* could be stuff here */ }
public class Foo2 : FooBase { /* could be stuff here */ }
public class Bar
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual SOMETHING WhichFoo { get; set }
}
...where WhichFoo deals with which FooBase to use (potentially string of "Foo1" but this seems quite messy).
With mappings:
public class FooBaseMap : ClassMap<FooBase>
{
public FooBaseMap()
{
this.Id(x => x.Id);
this.DiscriminateSubClassesOnColumn("Type");
}
}
public class Foo1Map : SubclassMap<Foo1>
{
public Foo1Map() { this.DiscriminatorValue("Foo1"); }
}
public class Foo2Map : SubclassMap<Foo2>
{
public Foo2Map() { this.DiscriminatorValue("Foo2"); }
}
What I want to be able to do is to create a new Foo, either 1 or 2, based on a value stored in Bar. So:
Bar bar = this.Session.Get<Bar>(1);
FooBase foo1 = bar.GetANewFoo(); // returns a new Foo1
Bar anotherBar = this.Session.Get<Bar>(123);
FooBase foo2 = bar.GetANewFoo(); // returns a new Foo2
Where GetANewFoo() could be a method, a property which returns an empty instance of Foo1 or Foo2.
Effectively what I want to do is to store the type of FooBase to be created by GetANewFoo in Bar.
What's the best way of going about this without explicitly having to manually write "Foo1" or "Foo2" to a Bar when I create one?
You can create a column in the Bar table which is going to save what kind of Foo it is. So, if this SOMETHING type of property is an enum, or a string, or an int (whatever), you can use switch-case statement to identify the kind of Foo, create what you need and return.
Just like this:
public FooBase GetANewFoo()
{
switch (WhichFoo)
{
case "Foo1": return new Foo1();
case "Foo2": return new Foo2();
default: return null;
}
}
Okay I think I got it - actually rehashing a method I used for the Strategy Pattern.
public abstract class FooFactoryBase
{
protected FooFactoryBase() { } // for NHibernate
protected FooFactoryBase(Guid id)
{
this.Id = id;
}
public virtual Guid Id { get; set; }
public virtual IList<Bar> Bars { get; set; }
public abstract FooBase CreateFoo();
}
public class Foo1Factory : FooFactoryBase
{
public readonly static Guid Guid = new Guid("abc123...");
public Foo1Factory() : base(Guid) { }
public override FooBase CreateFoo()
{
return new Foo1();
}
}
Then Bar becomes:
public class Bar
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual FooFactoryBase FooFactory { get; set; }
}
And mappings:
public class BarMap : ClassMap<Bar>
{
this.Id(x => x.Id);
this.Map(x => x.Name);
this.References(x => x.FooFactory);
}
public class FooFactoryBaseMap : ClassMap<FooFactoryBase>
{
this.Id(x => x.Id);
this.HasMany(x => x.Bars).Inverse();
this.DiscriminateSubClassesOnColumn("Id");
}
public class Foo1FactoryMap : SubClassMap<Foo1Factory>
{
this.DiscriminatorValue(Foo1Factory.Guid);
}
Now when I create my database I can populate it with all my FooFactorys, when adding Bars I can just load the appropriate Factory from the database and then call my code like so:
Bar bar = this.Session.Get<Bar>(10);
FooBase foo = bar.FooFactory.CreateFoo();
and the appropriate FooBase will be created.
Sometimes you just need to ask the question to figure it out :)
Related
Suppose I have two classes and both contain the same fields
Class A
{
public string Name { get; set; }
public int Designaton { get; set; }
}
Class B
{
public string Name { get; set; }
public int Designation { get; set; }
}
And I have one interface and two classes which are inherited from interface
public interface IDeprt
{
object BindData();
}
And two extractor classes:
public classAItem : IDeprt
{
public object BindData()
{
return new A()
{
// mapping operation
}
}
}
public classBItem : IDeprt
{
public object BindData()
{
return new B()
{
//same mapping operation
}
}
}
My question, how can I implement this in generic way using <T> .
Both classes are doing same operation only return type change. If I am doing in the above way there is lot of duplication of code.
Make your ITem interface and also BindData generic make them use the same generic parameter.
public interface IItem<T>
{
T BindData();
}
Then implement the subclasses like below :
public class AItem : ITem<A>
{
public A BindData(){
return new A(){
// mapping operation
}
}
}
public class BItem : ITem<B>
{
public B BindData(){
return new B(){
//same mapping operation
}
}
}
Edit : As the question evolves.
Make a shared base class for A and B classes.
public abstract class CommonItem
{
public string Name { get; set; }
public int Designaton { get; set; }
}
class A : CommonItem
{
}
class B : CommonItem
{
}
Then make class with a method that accepts a generic parameter with new and CommonItem constraints.
public class Binder
{
public T BindData<T>() where T: CommonItem, new()
{
return new T()
{
// you can access the properties defined in ICommonItem
}
}
}
Usage :
var binder = new Binder();
var boundA = binder.BindData<A>();
var boundB = binder.BindData<B>();
Say I have this object
public class foo
{
Ibar data {get; set;}
}
public interface Ibar
{
int id { get; set; }
}
public class bar : Ibar
{
public int id {get; set;}
public string a {get; set;}
}
public class bar2 : Ibar
{
public int id {get; set;}
public DateTime b {get; set;}
}
Now I implement a method like this one here
public something Method(foo f)
{
if(f.data is bar)
Console.WriteLine(((bar)f.data).doSomething());
else
Console.WriteLine(((bar2)f.data).doSomething());
}
public string doSomething(this bar b)
{
return b.a;
}
public string doSomething(this bar2 b)
{
return b.b.ToString();
}
So far so good (see). Is there a way to make this part here more elegant? in particular if I have more than one implementations of Ibar, it gets messy...
if(f.data is bar)
Console.WriteLine(((bar)f.data).doSomething());
else
Console.WriteLine(((bar2)f.data).doSomething());
UPDATE
So doSomething should be an extension method. That's why it isn't defined in the interface. So in other words: Im not allowed to change the interface or their implementations.
Are you trying to make dedicated extention class?
assuming you are doing so.
however you can achieve your goal with dynamic
public static class BarExtensions
{
public static string Something(this Ibar b)
{
return doSomething((dynamic)b);
}
public static string doSomething( bar b)
{
return b.a;
}
public static string doSomething(bar2 b)
{
return b.b.ToString();
}
}
so, you will required to call Something only, with Proper Type.
Here Type can be easily get by .GetType() of any object (so it won't be a problem)
I think you can do the type checks in one place because this is a good candidate for polymorphism. Since both bar and bar2 implement Ibar, you can change the definition of doSomething to the following.
public string doSomething(Ibar item)
{
return item is bar ? ((bar)item).a : ((bar2)item).b.ToString();
}
Now when you want to display it, this is how you handle your foo:
public void Method(foo f)
{
Console.WriteLine(f.data);
}
You just pass in the data property because the doSomething will know what to do with it when it receives it.
Update
Based on your comment, I'm expanding the code to use pattern matching as I suggested. Consider the following
public string doSomething(Ibar item)
{
switch (item)
{
case bar b:
return b.a;
case bar2 b:
return b.b.ToString();
case barX b:
return b.X.ToString();
default:
return item.GetType().ToString(); // Just in case...
}
}
where the definition of barX is
public class barX : Ibar
{
public int id {get; set; }
public object X {get; set; }
}
So whenever you add an implementation of Ibar, you cater for it in doSomething. All client code will remain unchanged because all they have to do is pass an Ibar to the doSomething method which uses pattern matching in the last example to determine what type the item is and it acts accordingly.
Final Edit
Seeing as you want to use overloads, you can use reflection but I don't know if that will qualify for your definition of elegant. In this case, it will not use switch statements and will find your methods as long as they are in the type this one is written in. Consider the following and change the defintion of my previously supplied DoSomething.
public static string ProcessThings(Ibar item)
{
var theType = item.GetType();
Console.WriteLine(theType.Name);
MethodInfo method = typeof(Program).GetMethods()
.Where(x => x.IsStatic && x.Name == "DoSomething" && x.ToString().Contains(theType.Name))
.SingleOrDefault();
var ret = method.Invoke(null, new object[] { item });
return ret?.ToString();
}
public static string DoSomething(barX item)
{
return "foo";
}
public static string DoSomething(bar2 item)
{
return "bar";
}
This way, you call the ProcessThings method (renamed for brevity but it can still stay as DoSomething) and it will figure out which one of your overloads to call.
If I remember well you can play with generic type constraints like this:
public something Method<T>(T f) where T : IBar
{
//Stuff here, where assures you f is always IBar
}
This should force the incoming parameter to be of the type you want.
This is the most elegant way I could think of.
Other are typeof and other conditional statements, which would require more in-method code anyway (if, else and so on).
EDIT:
Since OP seems having a hard time to understand I wrote a fully working code sample with Microsoft Unit Testing result.
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnitTests_ALL
{
[TestClass]
public class UnrelatedTests
{
[TestMethod]
public void InterfaceTest()
{
bar x = new bar { result = "Hi bar it's " };
bar2 xx = new bar2 { beforeResult = DateTime.Now };
Console.WriteLine(Method(x));
Console.WriteLine(Method(xx));
}
public string Method<T>(T f) where T : Ibar
{
return f.result;
}
}
public class foo
{
public foo(Ibar fooBar)
{
data = fooBar;
}
Ibar data { get; set; }
}
public interface Ibar
{
int id { get; set; }
string result { get; set; }
}
public class bar : Ibar
{
public int id { get; set; }
public string result { get; set; }
}
public class bar2 : Ibar
{
public int id { get; set; }
public DateTime beforeResult
{
set { result = value.ToString(); }
}
public string result { get; set; }
}
public static class Extensions
{
public static string doSomething(this bar b)
{
return b.result;
}
public static string doSomething(this bar2 b)
{
return b.result;
}
}
}
Here's the output:
I've inherited a bloated project that uses a huge class as an in-memory database:
public class Database
{
public class Parameter1
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter1Value> paramValues;
}
public class Parameter2
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter2Value> paramValues;
}
public class Parameter1Value
{
public string Value { get; set;}
public Parameter parameter { get; set;}
}
public class Parameter2Value
{
public int Value { get; set;}
public Parameter2 parameter { get; set;}
}
public List<Parameter1> parameter1List { get; set; }
public List<Parameter2> parameter2List { get; set; }
}
I am creating a generic method that creates instances of Parameter1 or Parameter2 (see below) and should add those to their respective lists, but I don't know how to use those types to get the parameter1List or parameter2List instances from my Database class. The Database class holds only one List<T> property for each defined type. Is this possible?
This is the generic method used to create instances:
public static Database Add<T>(this Database database, string code, string label) where T : new()
{
T itemToCreate = (T)Activator.CreateInstance(typeof(T));
itemToCreate.Code = code;
itemToCreate.Label = label;
var listForItem = database.GetList<T>; // This is the missing functionality
listForItem.Add(itemToCreate);
return database;
}
Here is a solution using interfaces and generic constraints.
Create an interface to represent a generic parameter class and add members to the interface as required:
public interface IParameter { ... }
And an interface to represent a list of parameters:
public interface IParameterList<TParameter> where TParameter : IParameter
{
List<TParameter> ParameterList { get; set; }
}
Have the Database and Parameter classes implement these new interfaces:
public class Parameter1 : IParameter
public class Parameter2 : IParameter
public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }
...
}
Add a where TParameter : IParameter constraint to your generic Parameter factory function, and have the factory function require an argument of type IParameterList<TParameter> which is an instance of the Database class. This satisfies the compiler that the Database class owns a list of TParameter. Now we just do db.ParameterList.Add(r) to add our new parameter to the correct list.
public static TParameter CreateParameter<TParameter>(IParameterList<TParameter> db) where TParameter : IParameter, new()
{
var r = new TParameter(); // This is the generic function you mentioned. Do stuff here to create your Parameter class.
db.ParameterList.Add(r); // Add the newly created parameter to the correct list
return r;
}
Code dump (full working version after I picked up your edit which added the generic factory function):
public class Parameter1 : IParameter
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter1Value> paramValues;
}
public class Parameter2 : IParameter
{
public string Code { get; set; }
public string Label { get; set; }
public List<Parameter2Value> paramValues;
}
public class Parameter1Value
{
public string Value { get; set; }
public Parameter parameter { get; set; }
}
public class Parameter2Value
{
public int Value { get; set; }
public Parameter2 parameter { get; set; }
}
public class Database : IParameterList<Parameter1>, IParameterList<Parameter2>
{
// Note: Setters for the List properties probably not needed here or in IParameterList as with the following code we instantiate them at class construction time and, in this MCVE at least, there are no further assignments
public List<Parameter1> parameter1List { get; set; } = new List<Parameter1>();
public List<Parameter2> parameter2List { get; set; } = new List<Parameter2>();
List<Parameter1> IParameterList<Parameter1>.ParameterList { get => parameter1List; set => parameter1List = value; }
List<Parameter2> IParameterList<Parameter2>.ParameterList { get => parameter2List; set => parameter2List = value; }
public static TParameter Add<TParameter>(IParameterList<TParameter> db, string code, string label) where TParameter : IParameter, new()
{
var itemToCreate = new TParameter();
itemToCreate.Code = code;
itemToCreate.Label = label;
db.ParameterList.Add(itemToCreate); // Add the newly created parameter to the correct list
return itemToCreate;
}
}
public interface IParameter
{
string Code { get; set; }
string Label { get; set; }
}
public interface IParameterList<TParameter> where TParameter : IParameter
{
List<TParameter> ParameterList { get; set; }
}
// Testing:
void Main()
{
var db = new Database();
Database.Add<Parameter1>(db, "hello", "hello2");
Database.Add<Parameter1>(db, "hello", "hello2");
Database.Add<Parameter2>(db, "hello", "hello2");
Console.WriteLine($"P1 count (should be 2): {db.parameter1List.Count()}; P2 count (should be 1): {db.parameter2List.Count}");
}
Output:
P1 count (should be 2): 2; P2 count (should be 1): 1
Here is a solution which acquires the target list using generics and reflection:
public static List<T> GetList<T>(this Database dataBase) where T : new()
{
return dataBase.GetType()
.GetProperties()
.Where(x => x.PropertyType == typeof(List<T>))
.Select(x => (List<T>)x.GetValue(dataBase))
.FirstOrDefault();
}
Credit: Michael Randall in the comments
I am trying to populate an array of objects that inherit from IFoo. The problem I am facing is that structure map is populating the property within IFoo with the same instance of IBar. I cannot add AlwaysUnique() to IBar because this is used elsewhere in our enterprise application and would have consequences.
Is there anyway that I can get it to create new instances of the Bar object for every Foo in the collection?
public interface IFoo
{
IBar bar { get; set; }
}
public class Foo1 : IFoo
{
public IBar bar { get; set; }
public Foo1(IBar bar) { this.bar = bar; }
}
public class Foo2 : IFoo
{
public IBar bar { get; set; }
public Foo2(IBar bar) { this.bar = bar; }
}
public interface IBar
{
Guid id { get; set; }
}
public class Bar : IBar
{
public Guid id { get; set; }
public Bar() {this.id = Guid.NewGuid();}
}
class Program
{
static void Main(string[] args)
{
var container = new Container(_ =>
{
_.Scan(x =>
{
x.TheCallingAssembly();
x.AddAllTypesOf<IFoo>();
});
_.For<IBar>().Use<Bar>(); //I can't change this line because Bar is used elsewhere in the project
});
var foos = container.GetAllInstances<IFoo>();
if (foos.ElementAt(0).bar == foos.ElementAt(1).bar)
throw new Exception("Bar must be a different instance");
}
}
You could do this with a custom policy. See example 3 here, you could adapt that to your needs.
Something like:
public class BarUniqueForFoo : IInstancePolicy
{
public void Apply(Type pluginType, Instance instance)
{
if (pluginType == typeof(IBar) && instance.ReturnedType == typeof(Bar)
{
instance.SetLifecycleTo<UniquePerRequestLifecycle>();
}
}
}
I am having a problem where by updating an entity does not update entities related to it. Here is an example of the code.
public class Foo
{
public int Id { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
public virtual string SomeString { get; set; }
}
public class Bar
{
public int Id { get; set; }
}
public class FooMapping : EntityTypeConfiguration<Foo>
{
public FooMapping()
{
HasKey(f => f.Id);
HasMany(f => f.Bars);
}
}
public class MyDb : DbContext
{
public IDbSet<Foo> Foos { get; set; }
public IDbSet<Bar> Bars { get; set; }
protected override vod OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Configurations.Add(new FooMapping());
}
}
I receive an update command containg a fooobject from an external application like this:
public void Update(Foo foo)
{
_myDb.Entry(foo).State = EntityState.Modified;
_myDb.SaveChanges();
}
This updates the SomeString value correctly, however the Bar objects are not modified.
I have tried doing the following:
public void Update(Foo foo)
{
foreach(Bar bar in foo.Bars)
{
_myDb.Entry(bar).State = EntityState.Modified;
}
_myDb.Entry(foo).State = EntityState.Modified;
_myDb.SaveChanges();
}
but this gives a DbUpdateConcurrencyException, with the following info
Store update, insert, or delete statement affected an unexpected
number of rows (0).
Entities may have been modified or deleted since entities were loaded. Refresh
ObjectStateManager entries.
How can I get the Bars to update without having to select them from the database?
Thanks
UPDATE
I have modified the Bar entity and the mappings as so.
public class Bar
{
public int Id { get; set; }
public virtual Foo Foo { get; set; }
}
public class FooMapping : EntityTypeConfiguration<Foo>
{
public FooMapping()
{
HasKey(f => f.Id);
HasMany(f => f.Bars).WithRequired(b => b.Foo);
}
}
public class BarMapping : EntityTypeConfiguration<Foo>
{
public BarMapping()
{
HasKey(b => b.Id);
HasRequired(b => b.Foo);
}
}
This doesn't change the anything. I should mention though that even with the first version using _myDb.Foos.Add(foo) works correctly (adding all Bars). However it is the update which does not.
You may notice that if Foo has new Bar items they will be added and (possibly) the existing ones will be nullified. You can try a few things:
Relate Bar to Foo:
public class Bar
{
public int Id { get; set; }
public virtual Foo Foo { get; set; }
}
public class FooMapping : EntityTypeConfiguration<Foo>
{
public FooMapping()
{
HasKey(f => f.Id);
HasMany(f => f.Bars)
.WithRequired(b => b.Foo); //check this syntax, I'm not entirely sure.
}
}
Try the above. What happened when I had a similar problem was that the "new" Bars where saved and the existing ones where nullified.
The next step you can try is to do a bit of manual deletion when updating:
public void Update(Foo foo)
{
var existing = _myDb.Find(foo.Id);
foreach(Bar bar in existing.Bars.ToList())
{
_myDb.Remove(bar);
}
existing.Bars.Clear();
foreach(Bar bar in foo.Bars)
{
existing.Bars.Add(bar);
}
// map other properties...
_myDb.SaveChanges();
}
Let me know if it works for you.