I've got a small integration service which recieves XML files and parses it.
Also I've created classes from provided XSD for deserializing XML data. During parsing I need to copy properties from those XSD-generated classes to my own that I use in Data Layer. This is an example of my aproach
var supplierInfo = new SupplierInfo();
//coping properties
supplierInfo.Name = supplier.name;
supplierInfo.ShortName = supplier.shortName;
supplierInfo.BrandName = supplier.brandName;
supplierInfo.AdditionalFullName = supplier.additionalFullName;
supplierInfo.AdditionalCode = supplier.additionalCode;
supplierInfo.AdditionalInfo = supplier.additionalInfo;
//lot's of other properties
//...
supplierInfo.Tax = supplier.tax;
supplierInfo.RegistrationDate = supplier.registrationDate;
Some times ammount of properties is very big. Is there more eligant way to copy those properties?
Automapper has been out there since ages ago. Tried and tested. http://automapper.org/
Here's an example:
using System;
using AutoMapper;
public class Program
{
class SupplierInfo
{
public SupplierInfo( string name, string shortName, string brandName ) {
Name = name;
ShortName = shortName;
BrandName = brandName;
}
public string Name {get; private set; }
public string ShortName {get; private set; }
public string BrandName {get; private set; }
}
class Supplier
{
public string name {get; set; }
public string shortName {get; set; }
public string brandName {get; set; }
}
public static void Main()
{
var dto = new Supplier() {
name = "Name 1",
shortName = "Short Name 1",
brandName = "Brand Name 1"
};
//From the tutorial:
//You only need one MapperConfiguration instance typically per AppDomain and should be instantiated during startup.
var config = new MapperConfiguration(cfg => cfg.CreateMap<Supplier, SupplierInfo>());
var mapper = config.CreateMapper();
SupplierInfo info = mapper.Map<SupplierInfo>(dto);
Console.WriteLine( info.Name );
Console.WriteLine( info.ShortName );
Console.WriteLine( info.BrandName );
}
}
The official Getting Started guide can be found at https://github.com/AutoMapper/AutoMapper/wiki/Getting-started
I am happy to be corrected on this but I always find automapper (as per the other answer), which maps property values by name/convention, a little scary to use in production code.
I don't really have a decent alternative but I prefer to do it manually as per your code sample - it's easier to read and debug and if you end up renaming any properties in a class, it will be clear that the copying code is broken (or if you use some IDE tool to rename the property, it'll change the copy code accordingly).
First, install EntityLite.Core:
PM> Install-Package EntityLite.Core
Then use it:
using inercya.EntityLite.Extensions;
...
supplierInfo.AssignPropertiesFrom(supplier);
EntityLite is a micro ORM I developed. It has some little gems :-)
EDIT:
I guess you may not want to install EntityLite.Core just to copy some properties from an object to another. So here you have an implementation of AssignPropertiesFrom extension method that uses Reflection:
public static class ObjectExtensions
{
public static void AssignPropertiesForm(this object target, object source)
{
if (target == null || source == null) throw new ArgumentNullException();
var targetPropertiesDic = target.GetType().GetProperties().Where(p => p.CanWrite).ToDictionary(p => p.Name, StringComparer.CurrentCultureIgnoreCase);
foreach (var sourceProp in source.GetType().GetProperties().Where(p => p.CanRead))
{
PropertyInfo targetProp;
if (targetPropertiesDic.TryGetValue(sourceProp.Name, out targetProp))
{
targetProp.SetValue(target, sourceProp.GetValue(source, null), null);
}
}
}
}
Incidentally, this is not the EntityLite implementation. EntityLite uses dynamic IL generation.
Related
I am trying to create a MongoDB like update document in my C# code. This is not used to update the MongoDB but the API I am using expects the data in this format.
I tried using MongoDB.Driver NuGet package and tried to create the document like this.
class Program
{
class MyTest
{
public string Name { get; set; } = String.Empty;
public string Description { get; set; } = String.Empty;
}
public static void Main()
{
var v = Builders<MyTest>.Update
.Set(t => t.Name , "TestName")
.Set(t => t.Description ,"TestDescription");
}
}
This code compiles and runs. But I need the output in string format. Something like:
$set: {Name:"TestName",Description:"TestDescription"}
Is there anyway to get a string representation like that?
This should work:
var output = v.Render(BsonSerializer.LookupSerializer<MyTest>(), new BsonSerializerRegistry());
This will render the Update document to a BsonValue.
public class Details
{
public int Id { get; internal set; }
public string Name { get; set; }
}
I have a task where a setter in a model has an internal attribute and I have tried adding stuff like
[assembly: InternalsVisibleTo("sometestrepo")]
over the model class but to no avail. I googled for a couple of hours and I can't seem to find an answer. Is it even possible to xunit test it or mock and object so that it would allow to create an object with an Id. Otherwise how else am I supposed to fully test CRUD methods that are all based around ID parameter?
The solution is to make private members that you want to test internal.
then you can add InternalsVisibleTo attribute.
[assembly: InternalsVisibleTo("sometestrepo")]
if you're using Moq,You can use something like that:-
var mockAddress = new Mock<Details>();
mockAddress.SetupGet(p => p.Id).Returns(42);
mockAddress.SetupGet(p => p.Name).Returns("Whatever you want to match");
var mockAddressRepository = new Mock<IRepository<Details>>();
var addresses = new List<Details> { mockAddress.Object };
mockAddressRepository.Setup(p => p.GetEnumerator()).Returns(addresses.GetEnumerator());
var addressToMatch = mockAddressRepository.Object.FirstOrDefault(address => address.Id == 42);
Console.WriteLine(addressToMatch.Name);
Expected Output Is:-
Whatever you want to match
One solution that might work is to use a fake.
In your Test class create a fake Details class, inheriting from Details. Then you could new up the property.
public class FakeDetails : Details
{
public new int Id { get; set; }
}
You could use the fake in your test then to set the properties.
var fakeDetails = new FakeDetails();
fakeDetails.Id = 15;
fakeDetails.Name = "Some Name";
I have a desktop app written in c# and I added app id and key id
and used this code to add data to database but the data is always empty or null.
var film = new Film();
film.setName(“soooft”);
film.setGenre(“aaa”);
film.setPlot(“fdgveqw”);
film.setUrl(“gdfwrw”);
var f = Backendless.Data.Of<Film>().Save(film);
I googled Backendless and it's a third-party solution. (See https://github.com/Backendless/.NET-SDK)
Usage gets explained at https://backendless.com/docs/dotnet/data_data_object.html
But I'm suspicious about why you use setName(), setGenre(), setPlot and setUrl in your code. Seems your Film class is missing properties. I would expect you'd be writing this instead:
var film = new Film();
film.Name = “soooft”;
film.Genre = “aaa”;
film.Plot = “fdgveqw”;
film.Url = “gdfwrw”;
But that would mean those fields are declared as public properties in your class like this:
public class Film
{
public string Name { get; set; }
public string Genre { get; set; }
public string Plot { get; set; }
public string Url { get; set; }
}
So I don't know why you have those setName and other methods. The Backendless API specifies that these fields need to be public properties so it can read them through reflection. Your code seems to suggests that they're not proper properties as indicated by their example and my code of the Film() class.
Make sure to use public get/set properties instead of private fields and the data will be saved properly.
Does anyone know why this works:
Mapper.Configuration.RecognizeDestinationPrefixes("Foo");
Mapper.CreateMap<A, B>();
But this doesn't:
Mapper.CreateProfile("FooPrefix").RecognizeDestinationPrefixes("Foo");
Mapper.CreateMap<A, B>()
.WithProfile("FooPrefix");
?
While this question is quite old now, I thought it would be useful to answer it given I spent ages trying to get profiles to work.
Although there are a bunch of ways to configure profiles, it seems that the only way what I could get it to work was as follows:
public class ExampleProfile : Profile
{
protected override void Configure()
{
ReplaceMemberName("Z", "A");
CreateMap<Source, Destination>(); // Notice this is CreateMap, NOT Mapper.CreateMap...
}
public override string ProfileName
{
get { return this.GetType().Name; }
}
}
Then, set up the profile in your config:
Mapper.Initialize(cfg => cfg.AddProfile<ExampleProfile>());
Given the Source and Destination classes as follows:
public class Source
{
public string Zabc { get; set; }
}
public class Destination
{
public string Aabc { get; set; }
}
This should now work:
var source = new Source { Zabc = "source" };
var dest = Mapper.Map<Destination>(source);
Assert.AreEqual(source.Zabc, dest.Aabc);
Profile names are different. You use FooxPrefix when creating the profile and then use FooPrefix when creating the map.
I'm in charge to migrate our own DAL to a solution based on Entity Framework 4 but, before I can do it, I need to be sure it's possible to translate all our "constructs" to this new technology.
One of the biggest issues I'm having is the possibility to read a field and build a custom type. Valid examples could be a bit mask saved in a BIGINT field, a list of mail addresses saved as a CSV list in a NVARCHAR field or an XML field containing aggregated data not worth to have their own table/entity. Basically the serialization mechanism is not fixed.
Let's take the classic "Address" example.
public class Address
{
public string Street {get; set;}
public string City {get; set;}
public string Zip {get; set;}
public string Country {get; set;}
}
and let's suppose we want to save it in an XML field using this template:
<address>
<street>Abrahamsbergsvägen, 73</street>
<city>Stockholm</city>
<zip>16830</zip>
<country>Sweden</country>
</address>
The question basically is: does exist a method to override how EF4 serializes and deserializes the content of a field mapped to a property of an entity?
I found this solution. It's not as clean as I wished but it seems it's impossible to get anything better.
given this base entity,
public class Institute
{
public int InstituteID { get; set; }
public string Name { get; set; }
// other properties omitted
}
I added in the database an XML field called Data containing some strings using this simple template
<values>
<value>Value 1</value>
<value>Value 2</value>
<value>Value 3</value>
</values>
In the entity I added these properties and I mapped the database field "Data" to the property "DataRaw".
protected string DataRaw
{
get
{
if (_Data == null)
return _DataRaw;
else
return new XElement("values", from s in Data select new XElement("value", s)).ToString();
}
set
{
_DataRaw = value;
}
}
private string _DataRaw;
private string[] _Data;
public string[] Data
{
get
{
if (_Data == null)
{
_Data = (from elem in XDocument.Parse(_DataRaw).Root.Elements("value")
select elem.Value).ToArray();
}
return _Data;
}
set
{
_Data = value;
}
}
This solution works. Here is the sample code:
class Program
{
static void Main(string[] args)
{
var ctx = new ObjectContext("name=TestEntities");
var institute = ctx.CreateObjectSet<Institute>().First();
System.Console.WriteLine("{0}, {1}", institute.InstituteID, institute.Name);
foreach (string data in institute.Data)
System.Console.WriteLine("\t{0}", data);
institute.Data = new string[] {
"New value 1",
"New value 2",
"New value 3"
};
ctx.SaveChanges();
}
}
Does anyone have a better solution?
Entity Framework does NOT serializes or deserializes entities nor it controls how the serialization should take place in other layers or modules of your application.
What you need to do is to simply open your POCO(s) and annotate their Properties with appropriate attributes that will be taken into account at the time of serialization when you want to ship them to your other application layers.