Implicit conversion between types in C# - c#

I have the following business objects:
public abstract class Product
{
public int Id { get; set; }
public bool OnStock { get; set; }
}
public class ProductForImport : Product
{
public int ImportId { get; set; }
}
public class ProductForExport : Product
{
public int ExportId { get; set; }
public bool IsExportable { get; set; }
public bool IsUsable { get; set; }
public string OtherParam {get; set;}
public static implicit operator ProductForExport(ProductForImport pfi)
{
ProductForExport p = new ProductForExport();
p.Id = pfi.Id;
p.IsExportable = true;
p.ExportId = 0;
return p;
}
}
so I can convert between the two types:
static void Main(string[] args)
{
ProductForExport pfe = new ProductForExport();
pfe.Id = 1;
pfe.OnStock = true;
ProductForImport pfi = new ProductForImport();
pfi.ImportId = 200;
ProductForExport pfe2 = (ProductForExport)pfi;
}
this works OK.
I have 100.000 ProductsForImport items.
If I understand correctly, if I convert them to ProductsForExport items, I'll have 100.000 +100.000 items in memory - that's reasonable.
My problem is: I have to send these "ProductForExport" objects through JSON services, each service just need some subset of the properties of each type:
servicecall1 should return ProductForExport1{ExportId,IsExportable}
servicecall2 should return ProductForExport2{ExportId,IsUsable}
Question: should I write an implicit conversion similar to the above example for these new types - ProductForExport1 and ProductForExport2 (so basically create 100.000+100.000 new objects)
or
somehow can I just "hide" the unwanted properties with some magic from the original type without the need to create new instances?
thanks,
b.

If you ned such kind of decoupling and separation of entities - you can create DTO object along with each business object and use DTO to communicate with Service.
But if you have a lot of business entities consider an other approach to avoid maintenance hell.
public sealed class ExportProductDto
{
public(ProductForExport exportProduct)
{
// initialize fields
this.ExportId = exportProduct.ExportId;
}
public int ExportId { get; private set; }
}
BTW,
An overkill solution with operator overload, use Adapter pattern to convert between product types
To decouple adapting from entities itself implement following interface your self:
public interface IProductAdapter<TImport, TExport>
{
TImport ToImportProduct(TExport exportProduct);
TExport ToExportProduct(TImport importProduct);
}
Or an other adapter approach:
// Implement this interface for ProductForImport class
// public class ProductForImport : IExportProductAdapter, Product
public interface IExportProductAdapter
{
ProductForExport ToExportProduct();
}
// Implement this interface for ProductForExport class
// public class ProductForExport : IImportProductAdapter, Product
public interface IImportProductAdapter
{
ProductForImport ToImportProduct();
}
EDIT: Answer to comments
// An example of IExportProductAdapter adapter implementation
public sealed class ProductForImport : Product, IExportProductAdapter
{
public int ImportId { get; set; }
public ProductForExport ToExportProduct()
{
ProductForExport p = new ProductForExport();
p.Id = this.Id;
p.IsExportable = true;
p.ExportId = 0;
return p;
}
}
And then instead of:
ProductForExport pfe2 = (ProductForExport)pfi;
You can do:
ProductForExport pfe2 = pfi.ToExportProduct();

I would create light objects specifically for returning through the service with only the required fields. Then use Automapper or something like that to map them.
I don't recommend using operator overloading if you can avoid it. I have seen many issues where a developer didn't realize when the operator overload was being called and something unexpected happened.

If you are using WCF, you can apply the IgnoreDataMemberAttribute to properties you wish not to serialize.

Have a look at the ScriptIgnoreAttribute to exclude properties from json serialization.

It took me a few reads but I don't think your problem is about implicit conversion as much as how to send data via json right?
If you have your object collections of Import or Export object you can use the JavaScriptSerilizer and some anonymous types to slice and dice what data you send.
You can use Linq to select specific properties of your object in a collection, and define an anonymous type "on-the-fly" to serialize out as a json string like this:
List<ProductForExport> exportList; //the list to export
JavaScriptSerializer jss = new JavaScriptSerializer();
string output = string.Empty;
output = jss.Serialize(new
{
isExportable = True, //static named properties
iTotalProducts = exportList.Count, //dynamic values
productDataArray = exportList //all data in an array object
});
//Or build the result using just a few properties of the collection:
foreach (ExportProduct exProd in exportList)
{
output += jss.Serialize(new
{
exProd.IsExportable,
exProd.ExportID
});
}

Related

How can I use a dynamic to find out when a property is used?

I would like to find out which of the properties in a source input object, a method has used. After executing the method I need to store in a database which of the properties was used.
The input could be any class with simple types, like this:
public class MyData : IMyData
{
public string A { get; set; }
public int B { get; set; }
public decimal C { get; set; }
}
I thought it could be done using an interface as input to the method, so I can replace the original object with a more advanced object, which stores usage of properties
public interface IMyData
{
string A { get; }
int B { get; }
decimal C { get; }
}
I can then
Create a dynamic object with the same properties
Use ImpromptuInterface to simulate the dynamic object implements my interface
Call my method with this dynamic interface
private static void Main()
{
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
IDictionary<string, object> replacementObject = new ExpandoObject();
replacementObject.Add("FieldsUsed", new List<string>());
foreach (var property in data.GetType().GetProperties())
replacementObject.Add(property.Name, property.GetValue(data));
var replacementInterface = replacementObject.ActLike<IMyData>();
DoStuff(replacementInterface);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)replacementObject["FieldsUsed"])}");
}
private static void DoStuff(IMyData source)
{
Console.WriteLine($"A is {source.A}");
if (source.B > 5)
Console.WriteLine($"C is {source.C}");
}
In the above example I would like to store that fields A and B have been used.
Only I am stuck at how I should store when a property is used by my DoStuff method.
You can write a wrapper like this:
public class ClassWrapper<T>: DynamicObject where T:class
{
private readonly T _obj;
private readonly List<string> _fieldsUsed=new List<string>();
public ClassWrapper(T obj)
{
_obj = obj;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
PropertyInfo propertyInfo = _obj.GetType().GetProperty(binder.Name);
_fieldsUsed.Add(binder.Name);
result = propertyInfo.GetValue(_obj);
return true;
}
public List<string> GetFieldsUsed() => _fieldsUsed;
public T GetWrapper()
{
return this.ActLike<T>();
}
}
and use it like
var data = new MyData { A = "Test", B = 3, C = new decimal(1.2) };
var mc=new ClassWrapper<IMyData>(data);
IMyData wrapped = mc.GetWrapper();
DoStuff(wrapped);
Console.WriteLine($"The method used these fields {string.Join(", ", (List<string>)mc.GetFieldsUsed())}");
If you want to know when a property is used, a Interface like INotifyPropertyChanged can do that for you at runtime. The exampel is only about notification for writes (that actually changed a value), but it would be trivial to expand it to reads and writes. It is not a perfect thing of course, as different executions might follow different code paths that use different properties.
If a function takes a specific type as input, you have to asume that all properties may be relevant. This is especially true for abstract types and interfaces - often the interface exists for this function. If it is one of those two, you can also always provide your own implementation of those Interfaces and Abstract class.
I can not shake the feeling that this is a XY problem.

ExpectedObjects compares concrete objects instead of only interfaces

I have an xUnit unit test project utilizing ExpectedObjects. Right now I'm trying to test a service that returns objects conforming to an interface. For the sake of the question let's take an example interface
public interface INamed
{
string Name { get; }
}
and two different implementations:
public class ComplexEntity : INamed
{
public int Id { get; set; }
public string Name { get; set; }
public string Domain { get; set; }
/* Many other properties follow... */
}
public class SimpleEntity : INamed
{
public int Id { get; set; }
public string Name { get; set; }
}
The method under test has a signature of
public IEnumerable<INamed> GetNames();
All that I care about is that the correct names are returned. So after mocking whatever dependencies the service might take I construct an expected result set as follows:
IEnumerable<INamed> expected = new []
{
new SimpleEntity { Name = "NAM1" },
new SimpleEntity { Name = "NAM2" },
...
}
And I compare them as follows:
// ACT
var result = systemUnderTest.GetNames();
// ASSERT
expected.ToExpectedObject().ShouldMatch(result);
This will fail. The collection that is actually returned by the GetNames under test is a mixed collection of both SimpleEntities and ComplexEntities, and none will match, because the Id properties of returned objects are non-zero, and other properties from ComplexEntity that I don't care about are not even present in the expected set.
The ExpectedObjects docs give me no guidance on this. The ShouldMatch is supposed to work on anonymous types, so this should (and does) work:
expected.Select(e => new { e.Name }).ToExpectedObject().ShouldMatch(result);
But I see this as an inflexible workaround. There are many other methods with contracts including only interfaces where I don't care about the underlying types. I would have to manually select the same properties from an interface in every such test and if that interface ever changed to include more properties the tests would still pass even though they wouldn't be correctly checking the contract. For example if I added the Id property to INamed, the test would still pass and would never even test for Id, allowing errors to go on silently.
Is there an out-of-the-box way to make ExpectedObjects compare only the public interfaces? I guess I could manually write a contrived, dynamic method creating an anonymous type out of an interface, make it generic and roll with it, something with usage like:
expected.ToExpectedObject().ShouldMatchInterface<INamed>(result);
but that makes me question using the library in the first place, as the effort put into ShouldMatchInterface would probably be significant.
It doesn't look like you're setting up the Expected Object correctly.
For example, with a GetNames() implementation like this:
public class Foo
{
public IEnumerable<INamed> GetNames()
{
return new[] {
new ComplexEntity() { Id = 1, Name = "NAM1", Domain = "DOM1" },
new ComplexEntity() { Id = 2, Name = "NAM2", Domain = "DOM2" }
};
}
}
The following xUnit + ExpectedObjects test will pass:
using ConsoleProject;
using ExpectedObjects;
using Xunit;
namespace ConsoleProject_Tests
{
public class ExpectedObjectsTests
{
[Fact]
public void GetNames_should_return_INamed_ExpectedObjects_Style()
{
var expected = new[]
{
new { Name = "NAM1" },
new { Name = "NAM2" }
}.ToExpectedObject();
var systemUnderTest = new Foo();
var actual = systemUnderTest.GetNames();
expected.ShouldMatch(actual);
}
}
}
Note that ToExpectedObject() is being fed anonymous objects, not concrete classes.
Now compare that with the old way of doing things by implementing a custom IEqualityComparer<INamed> which just happens to be on the test class...
using ConsoleProject;
using System;
using System.Collections.Generic;
using Xunit;
namespace ConsoleProject_Tests
{
public class ClassicXUnitTests : IEqualityComparer<INamed>
{
bool IEqualityComparer<INamed>.Equals(INamed x, INamed y)
{
if (x == null && y == null) return true;
if (x == null || y == null) return false;
return String.Equals(x.Name, y.Name);
}
int IEqualityComparer<INamed>.GetHashCode(INamed obj)
{
return obj.Name.GetHashCode();
}
[Fact]
public void GetNames_should_return_INamed_xUnit_Style()
{
var expected = new[]
{
new SimpleEntity() { Name = "NAM1" },
new SimpleEntity() { Name = "NAM2" }
};
var systemUnderTest = new Foo();
var actual = systemUnderTest.GetNames();
Assert.Equal<INamed>(expected, actual, this);
}
}
}
It still needs a concrete class that implements INamed because you can't just create a new abstract class or interface.

c#: how to hide a field which is used only for XML serialization retrocompatibility?

The field is used only during the serialization / deserialization process but I would like to immediately encapsulate it and hide from the class.
Is it possible?
Basically, no.
XmlSerializer only works with public members, so you can't make it internal or private. You can add some attributes to make it less glaring especially in UIs that data-bind:
[Browsable(false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public int Foo {get; set; }
but that only masks it. You could also look at IXmlSerializable, but that is a horrible API and most implementations of it are simply buggy - I do not recommend implementing this interface.
But: best practice is that whenever serialization requirements conflict with your model's design: create a dedicated DTO model - one that matches perfectly your chosen serialization library and exists purely for that purpose. And then map between the two. Then you don't have to compromise.
Its not possible with XML-Serialization in C# , if you want to do like that than you should make use of DataContractSerialization, It allows this kind of functionality i.e. you can serialize private field of you object.
Below is possible with DataContractSerialization, I hope you like to try out
[DataContract]
class Person
{
[DataMember]
public string m_name;
[DataMember]
private int m_age;
}
This what I tried when I was learning XML to Linq , and this is wired solution but if you want to try , here i created xml string by using xml to linq
here is my article : Object to XML using LINQ or XmlSerializer
Note : here code field of product class is private field but still you can generate xml string
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
class Program
{
public class Product
{
public Product()
{ }
public Product(string name,int code, List<productType> types)
{
this.Name = name;
this.Code = code;
this.types = types;
}
public string Name { get; set; }
private int Code { get; set; }
public List<productType> types { get; set; }
public string Serialize(List<Product> products)
{
XElement productSer = new XElement("Products",
from c in products
orderby c.Code
select new XElement("product",
new XElement("Code", c.Code),
new XElement("Name", c.Name),
new XElement("Types", (from x in c.types
orderby x.type//descending
select new XElement("Type", x.type))
))
);
return productSer.ToString();
}
}
public class productType
{
public string type { get; set; }
}
public static void Main()
{
List<productType> typ = new List<productType>();
typ.Add((new productType() { type = "Type1" }));
typ.Add((new productType() { type = "Type2" }));
typ.Add((new productType() { type = "Type3" }));
List<Product> products =new List<Product>() { new Product ( "apple", 9,typ) ,
new Product ("orange", 4,typ ),
new Product ("apple", 9 ,typ),
new Product ("lemon", 9,typ ) };
Console.WriteLine(new Product().Serialize(products));
Console.ReadLine();
}
}
Assuming you are using XmlSerializer, then only public fields and properties can be serialized, as explained in Troubleshooting Common Problems with the XmlSerializer:
The serializer examines all public fields and properties of the Type to learn about which types an instance references at runtime. It then proceeds to create C# code for a set of classes to handle serialization and deserialization using the classes in the System.CodeDOM namespace.
So, what are your options? If you are able to construct your XmlSerializer directly, you could make use of the XmlSerializer.UnknownElement event to forward the unknown elements to the object being deserialized for processing.
First, define the following attribute and extension methods:
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple = false)]
public class XmlUnknownElementEventHandlerAttribute : System.Attribute
{
}
public static partial class XmlSerializationHelper
{
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
{
serial = serial ?? new XmlSerializer(typeof(T));
serial.UnknownElement += UnknownXmlElementEventHandler;
using (StringReader reader = new StringReader(xmlString))
{
return (T)serial.Deserialize(reader);
}
}
public static void UnknownXmlElementEventHandler(object sender, XmlElementEventArgs e)
{
var obj = e.ObjectBeingDeserialized;
foreach (var method in obj.GetType().BaseTypesAndSelf()
.SelectMany(t => t.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
.Where(m => Attribute.IsDefined(m, typeof(XmlUnknownElementEventHandlerAttribute))))
{
method.Invoke(obj, BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { sender, e }, null);
}
}
}
public static class TypeExtensions
{
public static IEnumerable<Type> BaseTypesAndSelf(this Type type)
{
while (type != null)
{
yield return type;
type = type.BaseType;
}
}
}
Next, say you have some class like:
public partial class MyClass
{
public string MyValue { get; set; }
}
And some XML containing an element that needs to be post-processed and converted into the current model, e.g. <OldValue>:
<MyClass><OldValue>Hello</OldValue></MyClass>
Then add a method to MyClass that:
Can be private or internal (in full trust) or public;
Has the same signature as XmlElementEventHandler;
Is marked with your custom attribute [XmlUnknownElementEventHandler];
Performs the necessary post-processing on the old element.
And now the unknown element will be forwarded to it when using a serializer constructed by XmlSerializationHelper.LoadFromXml().
E.g., your method might look like:
public partial class MyClass
{
[XmlUnknownElementEventHandler]
void HandleOldElement(object sender, XmlElementEventArgs e)
{
if (e.Element.Name == "OldValue")
{
Debug.WriteLine("{0}: processed property {1} with value {2}", this, e.Element.Name, e.Element.OuterXml);
MyValue = "Old value was: " + e.Element.InnerText;
}
}
}
And you would deserialize as follows:
var model = xmlString.LoadFromXml<MyClass>();
One advantage of this solution is that it doesn't modify the XSD generated for your types in any way.
Sample fiddle. (Note that, because the dotnetfiddle code executes in partial trust, the handlers must be public. That's not necessary in full trust.)

Removing duplicates from a list<int,int> [duplicate]

I have to distinct list of object but NOT only by ID because sometimes two different objects have same ID.
I have class:
public class MessageDTO
{
public MessageDTO(MessageDTO a)
{
this.MsgID = a.MsgID;
this.Subject = a.Subject;
this.MessageText = a.MessageText;
this.ViewedDate = a.ViewedDate;
this.CreatedDate = a.CreatedDate;
}
public int? MsgID { get; set; }
public string Subject { get; set; }
public string MessageText { get; set; }
public System.DateTime? ViewedDate { get; set; }
public System.DateTime? CreatedDate { get; set; }
}
How I can distinct list of:
List<MessageDTO> example;
Thanks
Use LINQ.
public class MessageDTOEqualityComparer : EqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO a, MessageDTO b)
{
// your logic, which checks each messages properties for whatever
// grounds you need to deem them "equal." In your case, it sounds like
// this will just be a matter of iterating through each property with an
// if-not-equal-return-false block, then returning true at the end
}
public int GetHashCode(MessageDTO message)
{
// your logic, I'd probably just return the message ID if you can,
// assuming that doesn't overlap too much and that it does
// have to be equal on the two
}
}
Then
return nonDistinct.Distinct(new MessageDTOEqualityComparer());
You can also avoid the need for an extra class by overriding object.Equals(object) and object.GetHashCode() and calling the empty overload of nonDistinct.Distinct(). Make sure you recognize the implications of this decision, though: for instance, those will then become the equality-testing functions in all non-explicit scopes of their use. This might be perfect and exactly what you need, or it could lead to some unexpected consequences. Just make sure you know what you're getting into.
I you want to use other properties, you should implement IEqualityComparer interface. More on: msdn
class MsgComparer : IEqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO x, MessageDTO Oy)
{
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(MessageDTO m)
{
//it must br overwritten also
}
}
Then:
example.Distinct(new MsgComparer());
You could also overwrite Equals in MessageDTO class:
class MessageDTO
{
// rest of members
public override bool Equals(object obj)
{
// your stuff. See: http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
}
public override int GetHashCode()
{
}
}
Then it's enough:
example.Distinct();
You could use the extension method DistinctBy from the MoreLinq library:
string[] source = { "first", "second", "third", "fourth", "fifth" };
var distinct = source.DistinctBy(word => word.Length);
See here:
I recommend you using solution of #Matthew Haugen
In case you don't want to create a new class for that, there is a way to use LINQ by grouping you list by distinct field(s) then select the first item on this group. For example:
example.(e => new { e.MsgID, e.Subject }).Select(grp => grp.FirstOrDefault());

Relate two lists with LINQ extensions

I have two lists of different objects, one from a third party API and one from my database - and I'm trying to link the two as a relationship. Ideally with a similar effect of how DBML's create relationships for tables with foreign keys (Customer.Orders).
From third party:
class ApiObject {
public string ID { get; set; }
public string Title { get; set; }
public DateTime CreatedDate { get; set; }
... 30 other properties ...
}
From my database:
class DbmlObject {
public int ID { get; set; }
public string ApiID { get; set; }
public string OtherString { get; set; }
}
They are related through ApiObject.ID == DbmlObject.ApiID
I do not want to merge these, nor join them into some anonymous object (and explicitly list 30+ properties) - but rather to make the DbmlObject a linked property of ApiObject. i.e.: addressable as:
apiObject.DbmlObjects.First().OtherString or ideally apiObject.DbmlObject.OtherString since it is a 1 to 1 relationship.
In controller:
List<ApiObject> apiObjects = _thirdParty.GetObjects();
DbmlDataContext model = new DbmlDataContext();
List<DbmlObject> dbmlObjects = model.GetAllDbmlObjects();
// relate them here
foreach (var apiObject in apiObjects)
Console.Write(apiObject.DbmlObject.OtherString)
// NOTE: ideally this foreach loop should not make a DBML query on each iteration, just the single GetAllDbmlObjects query above.
It sounds like a join:
var combined = from api in apiObjects
join dbml in dbmlObjects on api.ID equals dbml.ApiID
select new { api, dbml }
In order to get DbmlObject "in" the ApiObject, you will need to either inherit ApiObject and construct a new one of that class, which includes the Dbml property, or create a entirely new class to return. If you need static typing this is the best you can do - of course you could (mis)use dynamic to get what you want.
In this case, you are mentioning (in comments) that the ApiObject class is from a third party library that you can't change - in this case I would probably choose to create a new type which takes an instance of both objects in the constructor and exposes the properties you need - a decorator. Yes, it looks like a lot of code, but it is not complex, good tools will autogenerate it for you - and you get the class that you need for your code to be succinct.
In case you want to go further with returning an IEnumerable<dynamic>, you could build a "combining dynamic" object based on DynamicObject that then responds to all the properties of ApiObject and DbmlObject - or just adds DbmlObject as a property. I am not saying this is the right way to go, it depends on what you need it for - remember you are losing type safety. Here is a simple example:
void Main()
{
dynamic dyn = new CombiningDynamic(new Foo { X = 3 }, new Bar { Y = 42 });
Console.WriteLine(dyn.X);
Console.WriteLine(dyn.Y);
}
public class Foo
{
public int X {get;set;}
}
public class Bar
{
public int Y { get;set;}
}
public class CombiningDynamic : DynamicObject
{
private object [] innerObjects;
public CombiningDynamic(params object [] innerObjects)
{
this.innerObjects = innerObjects;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
foreach(var instance in innerObjects)
{
Type t = instance.GetType();
PropertyInfo prop = t.GetProperty(binder.Name);
if (prop != null && prop.CanRead)
{
result = prop.GetValue(instance, null);
return true;
}
}
result = null;
return false;
}
}
Remember, this is example code. If you really go this way, you would want to perhaps override some more of the methods (TrySetMember, ...), and you most definetely would want to cache the reflection results so you don't need to walk the types each time - reflection is (comparatively) slow.

Categories

Resources