C# set property values in "bulk" (by excluding) - c#

In C# I have several classes where I have the following "logic":
//objA and objB are instances of the same class
objA.Property1 = objB.Property1;
objA.Property2 = objB.Property2;
objA.Property3 = objB.Property3;
objA.Property4 = objB.Property4;
.....
objA.Property40 = objB.Property40;
I do not want to apply the value to all the properties (but a big part of them).
This is getting repetitive and if somehow the "class" changes where there is a new property there is no compilation error and if the programmer does not pay attention there will be a bug because we will be losing that property change.....
I was wondering if there is a way to the following:
--> Apply the value of all the properties EXCLUDING the ones that specifically point, something like:
//possible syntax
objA.SetAllPropertiesLess(objB, x => x.Id && x.CreateDate && x.IsDeleted);
Does not need to be so "fancy" like this one, but for starting I would like to know if there is already something similar in the .NET framework, then if not, perhaps someone would already have an implementation (lightweight/fast).

Use AutoMapper.
Install it from nuget.org by following command:
PM> Install-Package AutoMapper
Then import it in class file and use it like below:
CreateMap<objA, objB>().ForDestinationMember(x => x.IsDeleted, opt => opt.Ignore());
Hope this will help you. Let me know if you have any doubt.

You can achieve that using AutoMapper and conditional mapping.

Related

Automapper - Creating Maps in C#

Was just getting started with AutoMapper and wanted to get clarity on something.
Let's say I want to seamlessly map between a User and a UserDto.
The examples all seem to suggest that I must first go to a startup area (for example WebApiConfig.cs or startup.cs or global.axax etc) and do something like this:
Mapper.CreateMap<User, UserDto>();
Presumably if I had 50 or 100 entities/DTOs that I wanted to map, I would need to literally add 50 or 100 lines of code with mappings between one class to another? Surely there's a smarter way, right?
If I don't ever need to do any specific mapping / overriding, do I really need to do this? I must have misunderstood the fundamentals of the framework because that just seems wrong to me.
Thanks!
As long as everything matches up on the source and the target, you could use DynamicMap:
var target = Mapper.DynamicMap<TSource, TTarget>(source);
However it would be more efficient to create a mapping as required:
if (Mapper.FindTypeMapFor<TSource, TTarget>() == null)
{
Mapper.CreateMap<TSource, TTarget>();
}
var target = Mapper.Map<TSource, TTarget>(source);

Missing SetRepresentation() method in C# MongoDB.Driver 2.0.0-beta1

I'm working with latest C# driver for MongoDB. I know it's beta now, but I think I'm doing some basic things.
What's my problem: I'm trying to set representation for my Id field to ObjectId instead of string like it is described in documentation:
BsonClassMap.RegisterClassMap<Entity>(cm =>
{
cm.AutoMap();
cm.IdMemberMap.SetRepresentation(BsonType.ObjectId);
});
But I can not do that because method SetRepresentation() does not exist. And I can not find anything similar.
So I wonder, was this method removed?
Is there any other way to set representation besides attributes? I can not use attributes because I don't have access to Entity class, I'm working with derived class.
Thanks in advance!
I've spoken with the developer of the driver and he clarified this situation:
We've brought all those options into the serializers themselves, so, in this case, you'll want to set the serializer. IdMemberMap.SetSerializer(new StringSerializer(BsonType.ObjectId)); //It's a string which will be represented as an ObjectId in the database.
this works for me (v2.2)
cm.MapIdMember(c => c.Id)
.SetSerializer(new StringSerializer(BsonType.ObjectId))
.SetIdGenerator(StringObjectIdGenerator.Instance);
it's represent objectId in database (not string)
"_id" : ObjectId("56715ebddb6986202816e566"),

Nhibernate QueryOver nested properties

Is there an easy way to use QueryOver with nested properties?
For example, I try something like this;
// SPLAT!
session.QueryOver<SuperHero>().Where(Expression.Eq("HomeBase.Name", "Bat Cave");
It won't work because it 'could not resolve property 'homebase.name' of SuperHero. That makes sense, but there is obviously some way to make this work, because if I use the older 'Query' approach I can get it to work just fine, i.e.
// The results I (technically) want.
sess.Query<SuperHero>().Where(x => x.HomeBase.Name == "The Bat Cave");
So what am I missing? I am guessing that there is some way to combine expressions, etc. to get the nexted properties to work with QueryOver, but what are they?
You can't do a nested property access like that--you'll have to join to the related table:
session.QueryOver<SuperHero>()
.JoinQueryOver(sh => sh.HomeBase)
.Where(hb => hb.Name == "Bat Cave");
Also you don't need to use strings in your restrictions--that's one of the great advantages of using QueryOver after all.

c# multiple expression parameteres

I'm trying to create a method signature that takes multiple properties of various type using
I would call it something like this:
AllPropertiesExcept(() => Property1, () => Property2)
This method almost work, except that the type of the properties have to be the same. I'm only going to use the property name, but want to use lambda expression to enable easy refactoring.
public static string MyMethod<T>(params Expression<Func<T>>[] propertyExpression)
I would use AllPropertiesExcept(params Expression<Func<object>>[] properties), you can still get the property names out of it, but it doesn't matter what type the property is.
Edit: However, I would tend to use it the other way round - instead of excluding properties I don't want to see, I would include properties I want to see. The reason is simple - to make your way work, you still need reflection - with my way, you could easily use the Func you get to get the actual data directly.
Edit 2 (getting the property name out of an expression):
Expression<Func<object>> obj = something; // you get this in your method
((obj.Body as UnaryExpression).Operand as MemberExpression).Member.Name
I can really advise you to use LinqPad for such things, you can easily drill down objects via Dump(), which displays the objects very user friendly. Just recreate a small example and experiment.
Does the method AllPropertiesExcept() return anything? Otherwise you could make a fluent interface (using method chaining):
AllPropertiesExcept(() => Property1)
.And(() => Property2)
.And(() => Property3);
Even if the AllPropertiesExcept() method returns something, you can defer the execution until you invoke a method at the end of the method chain:
var foo = AllPropertiesExcept(() => Property1)
.And(() => Property2)
.And(() => Property3)
.DoSomeThing();
I think what you need is to understand the ModelMetadata class documented here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.modelmetadata.aspx
This class is used in ASP.NET MVC in situations like Html.LabelFor(x -> x.Name)
An expression is passed to the ModelMetadata.FromLambdaExpression Method documented here:
http://msdn.microsoft.com/en-us/library/ee428393.aspx
After understanding how it is used in MVC, you could create your own code with some informed knowledge of how it was applied elsewhere.

Getting magic strings out of QueryOver (or Fluent NHibernate perhaps)?

One of the many reason to use FluentNHibernate, the new QueryOver API, and the new Linq provider are all because they eliminate "magic string," or strings representing properties or other things that could be represented at compile time.
Sadly, I am using the spatial extensions for NHibernate which haven't been upgraded to support QueryOver or LINQ yet. As a result, I'm forced to use a combination of QueryOver Lambda expressions and strings to represent properties, etc. that I want to query.
What I'd like to do is this -- I want a way to ask Fluent NHibernate (or perhaps the NHibernate QueryOver API) what the magic string "should be." Here's a pseudo-code example:
Currently, I'd write --
var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects("abc", other_object));
What I'd like to write is --
var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(session.GetMagicString<Shuttle>(x => x.Abc), other_object));
Is there anything like this available? Would it be difficult to write?
EDIT: I just wanted to note that this would apply for a lot more than spatial -- really anything that hasn't been converted to QueryOver or LINQ yet could be benefit.
update
The nameof operator in C# 6 provides compile time support for this.
There is a much simpler solution - Expressions.
Take the following example:
public static class ExpressionsExtractor
{
public static string GetMemberName<TObj, TProp>(Expression<Func<TObj, TProp>> expression)
{
var memberExpression = expression.Body as MemberExpression;
if (memberExpression == null)
return null;
return memberExpression.Member.Name;
}
}
And the usage:
var propName = ExpressionsExtractor.GetMemberName<Person, int>(p => p.Id);
The ExpressionsExtractor is just a suggestion, you can wrap this method in whatever class you want, maybe as an extension method or preferably a none-static class.
Your example may look a little like this:
var abcPropertyName = ExpressionsExtractor.GetMemberName<Shuttle, IGeometry>(x => x.Abc);
var x = session.QueryOver<Shuttle>().Add(SpatialRestriction.Intersects(abcPropertyName, other_object));
Assuming I'm understanding your question what you might want is a helper class for each entity you have with things like column names, property names and other useful things, especially if you want to use ICriteria searches. http://nhforge.org/wikis/general/open-source-project-ecosystem.aspx has plenty of projects that might help. NhGen (http://sourceforge.net/projects/nhgen/) creates very simple helper classes which might help point you down a design path for what you might want.
Clarification Edit: following an "I don't understand" comment
In short, I don't beleive there is a solution for you just yet. The QueryOver project hasn't made it as far as you want it to. So as a possible solution in the mean time, to remove magic strings build a helper class, so your query becomes
var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.Abc, other_object));
That way your magic string is behind some other property ( I just chose .Abc to demonstrate but I'm sure you'll have a better idea of what you want ) then if "abc" changes ( say to "xyz" ) you either change the property name from .Abc to .Xyz and then you will have build errors to show you where you need to update your code ( much like you would with lambda expressions ) or just change the value of the .Abc property to "xyz" - which would really only work if your property had some meaningfull name ( such as .OtherObjectIntersectingColumn etc ) not that property name itself. That does have the advantage of not having to update code to correct the build errors. At that point your query could be
var x = session.QueryOver<Shuttle>().Add(SpatialRestrictions.Intersects(ShuttleHelper.OtherObjectIntersectingColumn, other_object));
I mentioned the open source project ecosystem page as it can give you some pointers on what types of helper classes other people have made so your not re-inventing the wheel so to speak.

Categories