Steps to map classes using ValueInjector - collections

Quickly getting to the problem the mapping does not occur for the following code. Could someone explain why? or what i should do for the mapping to occur?
var parent = new Parent();
parent.ChildOne.Add(new ChildOne() { Name = "Child One" });
parent.ChildTwo.Add(new ChildTwo() { Name = "Child Two" });
AnotherParent anotherParent = new AnotherParent();
anotherParent.InjectFrom<LoopValueInjection>(parent);
Required Class are below
Anothher child one
public class AnotherChildOne
{
public string Name { get; set; }
}
Another child two
public class AnotherChildTwo
{
public string Name { get; set; }
}
Another Parent
public class AnotherParent
{
public ICollection<AnotherChildOne> ChildOne { get; set; }
public ICollection<AnotherChildTwo> ChildTwo { get; set; }
public AnotherParent()
{
ChildOne = new Collection<AnotherChildOne>();
ChildTwo = new Collection<AnotherChildTwo>();
}
}
Child Two
public class ChildTwo
{
public string Name { get; set; }
}
Child One
public class ChildOne
{
public string Name { get; set; }
}
Parent
public class Parent
{
public ICollection<ChildOne> ChildOne { get; set; }
public ICollection<ChildTwo> ChildTwo { get; set; }
public Parent()
{
ChildOne = new Collection<ChildOne>();
ChildTwo = new Collection<ChildTwo>();
}
}

I believe by default Value Injector will only inject the properties with the same name of the same type. You can get around this using a tweak to the CloneInjection sample from the Value Injector documentation as described here with this code:
public class CloneInjection : ConventionInjection
{
protected override bool Match(ConventionInfo c)
{
return c.SourceProp.Name == c.TargetProp.Name && c.SourceProp.Value != null;
}
protected override object SetValue(ConventionInfo c)
{
//for value types and string just return the value as is
if (c.SourceProp.Type.IsValueType || c.SourceProp.Type == typeof(string)
|| c.TargetProp.Type.IsValueType || c.TargetProp.Type == typeof(string))
return c.SourceProp.Value;
//handle arrays
if (c.SourceProp.Type.IsArray)
{
var arr = c.SourceProp.Value as Array;
var clone = Activator.CreateInstance(c.TargetProp.Type, arr.Length) as Array;
for (int index = 0; index < arr.Length; index++)
{
var a = arr.GetValue(index);
if (a.GetType().IsValueType || a.GetType() == typeof(string)) continue;
clone.SetValue(Activator.CreateInstance(c.TargetProp.Type.GetElementType()).InjectFrom<CloneInjection>(a), index);
}
return clone;
}
if (c.SourceProp.Type.IsGenericType)
{
//handle IEnumerable<> also ICollection<> IList<> List<>
if (c.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
{
var t = c.TargetProp.Type.GetGenericArguments()[0];
if (t.IsValueType || t == typeof(string)) return c.SourceProp.Value;
var tlist = typeof(List<>).MakeGenericType(t);
var list = Activator.CreateInstance(tlist);
var addMethod = tlist.GetMethod("Add");
foreach (var o in c.SourceProp.Value as IEnumerable)
{
var e = Activator.CreateInstance(t).InjectFrom<CloneInjection>(o);
addMethod.Invoke(list, new[] { e }); // in 4.0 you can use dynamic and just do list.Add(e);
}
return list;
}
//unhandled generic type, you could also return null or throw
return c.SourceProp.Value;
}
//for simple object types create a new instace and apply the clone injection on it
return Activator.CreateInstance(c.TargetProp.Type)
.InjectFrom<CloneInjection>(c.SourceProp.Value);
}
}
If you include the above CloneInjection code you will want to do this:
anotherParent.InjectFrom<CloneInjection>(parent);
instead of:
anotherParent.InjectFrom<LoopValueInjection>(parent);

Related

System.Text.Json.JsonSerializer doesn't serialize properties from derived classes

I can't have System.Text.Json.JsonSerializer serializing properties from derived classes. Newtonsoft has no issues doing the job.
namespace TestJson
{
class Program
{
static void Main(string[] args)
{
var myClass = new NewClass2
{
Value1 = "qsd",
ShouldBeSerialized = "why am I not serialized?"
};
// as expected, getting {"ShouldBeSerialized":"why am not serialized?","Value1":"qsd"}
var textJsonSerializedFromTop = System.Text.Json.JsonSerializer.Serialize<NewClass2>(myClass);
// expecting {"ShouldBeSerialized":"why am not serialized?","Value1":"qsd"}
// but getting {"Value1":"qsd"}
var textJsonSerializedFromBase = System.Text.Json.JsonSerializer.Serialize<ClassBase>(myClass);
// as expected, getting {"ShouldBeSerialized":"why am not serialized?","Value1":"qsd"}
var newtonSoftSerializedFromBase = Newtonsoft.Json.JsonConvert.SerializeObject(myClass);
}
}
public class ClassBase
{
public string Value1 { get; set; }
}
public class NewClass2 : ClassBase
{
public string ShouldBeSerialized { get; set; }
}
}
In the previous example to show the actual issue, the solution is straight forward, but in the following one, I have no clue how to manage by not using newtonsoft:
namespace TestJson
{
class Program
{
static void Main(string[] args)
{
var toSerialize =
new[] {
new ClassBase
{
Value1 = "aze"
},
new NewClass2
{
Value1="qsd",
ShouldBeSerialized="why am I not serialized?"
}
};
var textJsonSerialized = System.Text.Json.JsonSerializer.Serialize(toSerialize);
// expecting [{"Value1":"aze"},{"ShouldBeSerialized":"why am not serialized?","Value1":"qsd"}]
// but getting [{"Value1":"aze"},{"Value1":"qsd"}]
Console.WriteLine(textJsonSerialized);
var newtonSoftSerialized = Newtonsoft.Json.JsonConvert.SerializeObject(toSerialize);
// as expected getting [{"Value1":"aze"},{"ShouldBeSerialized":"why am not serialized?","Value1":"qsd"}]
Console.WriteLine(newtonSoftSerialized);
}
}
public class ClassBase
{
public string Value1 { get; set; }
}
public class NewClass2 : ClassBase
{
public string ShouldBeSerialized { get; set; }
}
}

Dynamically attach entry to context

I am using .Net 4.5 and Entity Framework 6 to create a REST Web API.
In my Update methods I need to attach the object recieved in the web api, back to the dbcontext. I have achieved this using the code below. What I want to do now, is to make this code reusable so that I can call AttachToContext for any object in the model.
I understand that I have to use generic type T and TEntity, but I cannot find any suitable examples.
//Repository.cs
public void UpdateOrderItem(OrderItem orderItem)
{
try
{
AttachToContext(orderItem);
_context.SaveChanges();
}
catch (Exception e)
{
}
}
private void AttachToContext(OrderItem orderItem)
{
var entry = _context.Entry<OrderItem>(orderItem);
if (entry.State == EntityState.Detached)
{
var attachedEntity = FindExistingEntity(orderItem.Id);
if (EntityExists(attachedEntity))
{
UpdateEntityValues(attachedEntity, orderItem);
}
else
{
entry.State = EntityState.Modified;
}
}
}
private OrderItem FindExistingEntity(int id)
{
var set = _context.Set<OrderItem>();
return set.Find(id);
}
private void UpdateEntityValues(OrderItem existing, OrderItem updated)
{
var attachedEntry = _context.Entry(existing);
attachedEntry.CurrentValues.SetValues(updated);
}
private bool EntityExists(object entity)
{
return entity != null;
}
Your AttachToContext has dependency to primary key property, orderItem.Id, to change it into dynamic, you can introduce an interface and implement to all entities you have or just passing the id as parameters.
Interface
public interface IEntity
{
public int Id { get; set; }
}
public class OrderItem : IEntity
{
// body
}
Then modify the AttachToContext as follow.
private void AttachToContext<T>(T entity) where T : class, IEntity
{
var entry = _context.Entry(entity);
if (entry.State == EntityState.Detached)
{
var attachedEntity = FindExistingEntity<T>(entity.Id);
if (EntityExists(attachedEntity))
{
UpdateEntityValues(attachedEntity, entity);
}
else
{
entry.State = EntityState.Modified;
}
}
}
private T FindExistingEntity<T>(int id) where T : class
{
var set = _context.Set<T>();
return set.Find(id);
}
private void UpdateEntityValues<T>(T existing, T updated) where T : class
{
var attachedEntry = _context.Entry(existing);
attachedEntry.CurrentValues.SetValues(updated);
}
The usage would be AttachToContext(orderItem);.
Passing The Keys
private void AttachToContext<T>(T entity, params object[] id) where T : class
{
var entry = _context.Entry(entity);
if (entry.State == EntityState.Detached)
{
var attachedEntity = FindExistingEntity<T>(id);
if (EntityExists(attachedEntity))
{
UpdateEntityValues(attachedEntity, entity);
}
else
{
entry.State = EntityState.Modified;
}
}
}
private T FindExistingEntity<T>(object[] id) where T : class
{
var set = _context.Set<T>();
return set.Find(id);
}
private void UpdateEntityValues<T>(T existing, T updated) where T : class
{
var attachedEntry = _context.Entry(existing);
attachedEntry.CurrentValues.SetValues(updated);
}
The usage would be AttachToContext(orderItem, orderItem.Id);.
Another alternative would be using object set to get the primary key properties, then using reflection to get the value. To get the primary key properties has been explained in this post.

How to show sum using LINQ statement in Grid view of the MVC app

I developing the MVC application.
I am stuck in LINQ Syntax.
I wan to show the sum of List Items in index view of parent.
Please check code below.
In Model I have two classes.
public class StockAdjustment
{
public int Id { get; set; }
public List<StockAdjustmentItem> StockAdjustmentItems { get; set; }
public int SumOfStockAdjustmentItemQuantity
{
get
{
if (this.StockAdjustmentItems != null)
{
return this.StockAdjustmentItems.Sum(s=>s.OriginalQuantity);
}
return 0;
}
}
}
public class StockAdjustmentItem
{
public int Id { get; set; }
public int OriginalQuantity { get; set; }
public StockAdjustment StockAdjustment { get; set; }
}
public StockAdjustment GetAll(int Id)
{
oStockAdjustment = GetStockAdjustmentById(Id);
var prepo = new ProductRepo();
oStockAdjustment.StockAdjustmentItems = new List<StockAdjustmentItem>();
StockAdjustmentItem ai1 = new StockAdjustmentItem();
ai1.Id = 1 ;
ai1.OriginalQuantity = 250;
oStockAdjustment.StockAdjustmentItems.Add(ai1);
StockAdjustmentItem ai2 = new StockAdjustmentItem();
ai2.Id = 1;
ai2.OriginalQuantity = 375;
oStockAdjustment.StockAdjustmentItems.Add(ai2);
return oStockAdjustment;
}
Now I have controller Code
public ActionResult Index(string searchContent = "")
{
AdjustmentRepo oAdjustmentRepo = new AdjustmentRepo();
var adjustments = from adjustment in oAdjustmentRepo.GetAll() select adjustment;
ViewBag.StockAdjustmentList = adjustments;
return View(adjustments);
}
This Working perfectly fine...
Now, the problem comes when, I am trying to show StockAdjustment in List.
I have to show the sum of the OriginalQuantites of StockAdjustmentItems in the Front of StockAdjustment item in grid.
in above Exmaple I want to show 650(250 + 375) in the row of a gird.
#model IEnumerable<StockWatchServices.DomainClass.StockAdjustment>
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c=>c.StockAdjustmentItems.Sum( OriginalQuantity ???? Im stuck here... )
}
What should I write here ?
I can see like this...
Create a getter only property on the StockAdjustment class
public class StockAdjustment
{
public int Id { get; set; }
public List<StockAdjustmentItem> StockAdjustmentItems { get; set; }
public int SumOfStockAdjustmentItemQuantity
{
get
{
if (this.StockAdjustmentItems != null)
{
return this.StockAdjustmentItems.Sum(s=>s.OriginalQuantity);
}
return 0;
}
}
}
And then in your Razor view:
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c => c.SumOfStockAdjustmentItemQuantity)
}
Can you try with below code :
#Html.Grid(Model).Columns(columns =>
{
columns.Add(c => c.StockAdjustmentItems.Where(quantity => quantity.OriginalQuantity != null).Sum(sum => sum.OriginalQuantity).ToString());
})

Bind Menu To a List in ASP.NET

How to bind a list to ASP.NET Menu control?
try something like this .
This is just example how you bind data to the menu control using asp.net.. you can bind list also same way like this....
Start with a IHierarcyData class that will store each string from the StringCollection...
public class MyMenuItem : IHierarchyData
{
public MyMenuItem(string s)
{
Item = s;
}
public override string ToString()
{
return Item.ToString();
}
#region IHierarchyData Members
public IHierarchicalEnumerable GetChildren()
{
return null;
}
public IHierarchyData GetParent()
{
return null;
}
public bool HasChildren
{
get { return false; }
}
public object Item
{
get; set;
}
public string Path
{
get { return string.Empty; }
}
public string Type
{
get { return string.Empty; }
}
#endregion
}
Build a class that will be the collection...
public class MyMenu : StringCollection, IHierarchicalEnumerable
{
List<IHierarchyData> _list = new List<IHierarchyData>();
public void Add(StringCollection strings)
{
foreach (string s in strings)
{
MyMenuItem i = new MyMenuItem(s);
_list.Add(i);
}
}
#region IHierarchicalEnumerable Members
public IHierarchyData GetHierarchyData(object enumeratedItem)
{
return enumeratedItem as IHierarchyData;
}
#endregion
#region IEnumerable Members
public System.Collections.IEnumerator GetEnumerator()
{
return _list.GetEnumerator();
}
#endregion
}
In the page you can now construct the menu...
MyMenu pos = new MyMenu();
StringCollection sc = new StringCollection();
sc.Add("First");
sc.Add("Second");
pos.Add(sc);
Menu1.DataSource = pos;
Menu1.DataBind();

Nunit tests on Response.Cache.VaryByHeader

I am doing some Unit testing with NUnit and NSubstitute on a function that uses HttpResponse, I know you can't mock these objects so I have created interfaces to represent them and some of there properties.
I'm having trouble understanding how to create an interface for Response.Cache.VaryByHeader
// This is my HttpResponse interface
public interface IHttpResponse
{
Stream Filter { get ; set; }
IHttpCachePolicy Cache { get; set; }
void AppendHeader(string name, string value);
}
// concrete httresponse
public class HttpResponseProxy : IHttpResponse
{
private HttpResponse _httpResponse;
public Stream Filter {
get {
return _httpResponse.Filter ?? new MemoryStream();
}
set { _httpResponse.Filter = value; }
}
public IHttpCachePolicy Cache
{
get { return new HttpCachePolicyProxy(_httpResponse.Cache); }
set { }
}
public HttpResponseProxy(HttpResponse httpResponse)
{
if (httpResponse == null)
{
throw new ArgumentNullException("httpResponse");
}
_httpResponse = httpResponse;
_httpResponse.Filter = httpResponse.Filter;
}
public void AppendHeader(string name, string value)
{
_httpResponse.AppendHeader(name, value);
}
}
// HttpCachePolicy interface
public interface IHttpCachePolicy
{
IHttpCacheVaryByHeaders VaryByHeaders { get; set; }
}
// concrete HttpCachePolicy
public class HttpCachePolicyProxy : IHttpCachePolicy
{
private HttpCachePolicy _httpCachePolicy;
public HttpCachePolicyProxy(HttpCachePolicy httpCachePolicy)
{
_httpCachePolicy = httpCachePolicy;
}
public IHttpCacheVaryByHeaders VaryByHeaders
{
get { return new HttpCacheVaryByHeadersProxy(_httpCachePolicy.VaryByHeaders as HttpCacheVaryByHeaders); }
set { }
}
}
public interface IHttpCacheVaryByHeaders
{
IHttpCacheVaryByHeaders HttpCacheVaryByHeaders { get; set; }
}
public class HttpCacheVaryByHeadersProxy : IHttpCacheVaryByHeaders
{
private HttpCacheVaryByHeaders _httpCacheVaryByHeaders;
public HttpCacheVaryByHeadersProxy(HttpCacheVaryByHeaders httpCacheVaryByHeaders)
{
_httpCacheVaryByHeaders = httpCacheVaryByHeaders;
}
public IHttpCacheVaryByHeaders HttpCacheVaryByHeaders
{
get { return new HttpCacheVaryByHeadersProxy(_httpCacheVaryByHeaders); }
set { }
}
}
This is the function i am actually testing:
public static void CompressPage(IHttpRequestGetCompressionMode getCompressionMode, IHttpResponse httpResponse)
{
string supportedCompression = getCompressionMode.GetClientSupportedCompressionMode();
if (supportedCompression != HttpHeaderValues.NoCompression)
{
switch (supportedCompression)
{
case HttpHeaderValues.DeflateCompression:
httpResponse.Filter = new DeflateStream(httpResponse.Filter, CompressionMode.Compress);
break;
case HttpHeaderValues.GZipCompression:
httpResponse.Filter = new GZipStream(httpResponse.Filter, CompressionMode.Compress);
break;
}
httpResponse.AppendHeader(HttpHeaderValues.ContentEncodingHeader, supportedCompression);
// this line is where i have the problem
httpResponse.Cache.VaryByHeaders[HttpHeaderValues.AcceptEncodingHeader] = true;
}
}
I'm getting "cannot apply index to an expression of type IHttpCacheVaryByHeaders" errors.
I have the interface for the response and cache but how do I represent VaryByHeaders in an interface and then use it in a concrete class?
The error seems to suggest that IHttpCacheVaryByHeaders does not have an indexer declared (e.g. bool this[string header] { get; set; }), but rather than implementing these wrappers yourself, try the HttpResponseWrapper and other System.Web.Abstractions. This will should make testing this stuff a lot easier. :)

Resources