In the below example, I'm just trying to get Test_Person_Name.FirstName to map to something (anything) in TestPersonFlattened. At this point, considering the amount of time I've sunk into this, I'm not too hung up on what the destination property name is..I just want it to work.
public class Test_Person
{
public Test_Person_Name Test_Person_PublicName { get; set; }
}
public class Test_Person_Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestPersonFlattened
{
public string Test_Person_PublicNameFirstName { get; set; } // What do I call this property?
}
AutoMapper.Mapper.CreateMap<Test_Person, TestPersonFlattened>();
AutoMapper.Mapper.AssertConfigurationIsValid();
It seems like Test_Person_PublicNameFirstName should work, but I get an exception on AssertConfigurationIsValid(). I've also tried TestPersonPublicNameFirstName, Test_Person_PublicName_FirstName as destination property names.
It'd be unfavorable to rename the source property name, just because the source library is used in many other projects. Also, a ForMember() call isn't ideal, but I'll do it if there's no other option.
One way to do it would be to simply leave out "Test_Person_" from the PublicNameFirstName property of your TestPersonFlattened class, and use RecognizePrefixes() to make it so that AutoMapper ignores "Test_Person_" when attempting to map property names.
The following code succeeds:
public partial class App : Application
{
public App()
{
Mapper.Initialize(cfg =>
{
cfg.RecognizePrefixes("Test_Person_");
cfg.CreateMap<Test_Person, TestPersonFlattened>();
});
Mapper.CreateMap<Test_Person, TestPersonFlattened>();
Mapper.AssertConfigurationIsValid();
}
}
public class Test_Person
{
public Test_Person_Name Test_Person_PublicName { get; set; }
}
public class Test_Person_Name
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestPersonFlattened
{
public string PublicNameFirstName { get; set; } // This is what I call this property!
}
Related
I am getting a rather weird casting error. Here is the code:
public class OrganizationLocation : IOrganizationLocation
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public interface IOrganizationLocation
{
string Name { get; }
}
public class Organization : IOrganization
{
public Guid Id { get; set; }
public string Alias { get; set; }
public virtual ICollection<OrganizationLocation> Location { get; set; }
public ICollection<IOrganizationLocation> Locations
{
get
{
return (ICollection<IOrganizationLocation>) Location;
}
}
}
public interface IOrganization
{
string Alias { get; }
ICollection<IOrganizationLocation> Locations { get; }
}
now when I try to run this via a service (backend data layer is EF6), the "Location" variable has all the values, however, the "Locations" variable fails to cast. If I try to do a safe cast, it comes back as null every time.
I'm not understanding why would the cast fail? It has same fields, both are ICollection Type, so why do I get a HashSet?
The reason why I am doing it this way is because for EF6 framework to be able to treat this class as a table it needs to have a concrete type and a public get/set. However, I do not wish to expose that, so I use interface instead and then inject the class when the interface is called. This way I only expose get method and on top of it I only expose interface layers.
Unable to cast object of type 'System.Collections.Generic.HashSet`1[Namespace.OrganizationLocation]' to type 'System.Collections.Generic.ICollection`1[Namespace2.IOrganizationLocation]'.
I was able to resolve this by changing the code to the following:
public class OrganizationLocation : IOrganizationLocation
{
public Guid Id { get; set; }
public string Name { get; set; }
}
public interface IOrganizationLocation
{
string Name { get; }
}
public class Organization : IOrganization
{
public Guid Id { get; set; }
public string Alias { get; set; }
public virtual ICollection<OrganizationLocation> Location { get; set; }
public IEnumerable<IOrganizationLocation> Locations => Location
}
public interface IOrganization
{
string Alias { get; }
IEnumerable<IOrganizationLocation> Locations { get; }
}
I have an application serving multiple websites and would like to setup colour scheming like this:
Each element (link, text, heading, etc) has a default for the application
Each element can be overridden for individual websites
If an element is set to application default, the custom colour should be remembered for future reference
Website Configuration.cs
public class WebsiteConfiguration
{
public ApplicationConfiguration ApplicationConfiguration { get; set; }
public string CustomLinkColour { get; set; }
public bool IsCustomLinkColourActive { get; set; }
public string LinkColour
{
get
{
return (IsCustomLinkColourActive ? CustomLinkColour : ApplicationConfiguration.DefaultLinkColour);
}
}
public string CustomTextColour { get; set; }
public bool IsCustomTextColourActive { get; set; }
public string TextColour
{
get
{
return (IsCustomTextColourActive ? CustomTextColour : ApplicationConfiguration.DefaultTextColour);
}
}
// ...and so on for each colour scheme element...
}
ApplicationConfiguration.cs
public class ApplicationConfiguration
{
public List<WebsiteConfiguration> WebsiteConfigurations { get; set; }
public string DefaultLinkColour { get; set; }
public string DefaultTextColour { get; set; }
//... and so on for each colour scheme element...
}
Problems
It's a lot of work!
There are just 2 colour scheme elements in the examples above, but there may be 50+ of them.
Also, it is creating a lot of work in the view files, with if else blocks etc.
Attempted Solution
A ColourSchemeItem class manages the logic.
public class ColourSchemeItem
{
public string DefaultColour { get; set; }
public string CustomColour { get; set; }
public bool IsCustomColourActive { get; set; }
public string ActiveColour
{
get
{
return (IsCustomColourActive ? CustomColour : DefaultColour);
}
}
}
And then WebsiteConfiguration becomes much simpler...
public class WebsiteConfiguration
{
public ApplicationConfiguration ApplicationConfiguration { get; set; }
public ColourSchemeItem Link { get; set; }
public ColourSchemeItem Text { get; set; }
// ...and so on for each colour scheme element...
}
However...
But somehow I need to get the default colour from the ApplicationConfiguration into the ColourSchemeItem. And I can't figure out how.
If the ColourSchemeItem contains a reference to it's parent - WebsiteConfiguration - I get a No Key Defined for Entity error.
If ColourSchemeItem does NOT contain a reference to it's parent, I can't access the default colour from WebsiteConfiguration.ApplicationConfiguration.
The only other option I can think of it to access the DB directly from within the ColourSchemeItemclass. If there are going to be 50+ of these, I don't want to do that.
Create a custom constructor, and set the default to AplicationConfiguration
I have two classes:
public class ClassA
{
public ClassA()
{
LanguageInfo = new List<ClassALanguage>();
}
public long ID { get; set; }
public string Value { get; set; }
public List<ClassALanguage> LanguageInfo { get; set; }
}
public class ClassALanguage
{
public long ID { get; set; }
public string Name { get; set; }
public string Language { get; set; }
}
And I have a destination class:
public class WSClassA
{
public long ID { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
So I thought I could configure the mapping like this:
Mapper.CreateMap<ClassA, WSClassA>()
.ForMember(
ws => ws.Name,
opt => opt.MapFrom(clsA => clsA.LanguageInfo.Find(lg => lg.Language == languageSelected).Name));
The problem is after the first time the mapping is executed, it is not able to change. Even if the CreateMap() is executed with another value for languageSelected, the binding works as the first time.
Is there any solution to accomplish that?
In your case you need some context when you perform your mapping - the selected language.
Instead of using MapFrom use the ResolveUsing method with a custom IValueResolver.
See - https://automapper.codeplex.com/wikipage?title=Custom%20Value%20Resolvers
When you make your .Map call use the overload which allows you to modify the IMappingOperationOptions. Set the language you want to compare against in the interfaces Items collection.
Finally in your custom IValueResolver's Resolve method you can access those items via ResolutionResult.Context.Options.Items property.
I have an application that can contain a minimum of one "person" up to a maximum of fours "persons". I am using view models and manually mapping in the controller to the domain model.
I am completely lost as to how to include more than one "person" in the app. I've read up on using for but can't wrap my head around it.
Right now, I am just adding the data from the "person" class manually such that
Code:
public class SomeClass
{
public Guid SomeClassId {get; set;}
public string BorrowerFirst { get; set; }
public string BorrowerMI { get; set; }
public string BorrowerLast { get; set; }
public Suffix? BorrowerSuffix { get; set; }
... some more fields ...
}
and so on in the master class.
What I'd like to do is use a class such as:
Code:
public class Applicant
{
public string BorrowerFirst { get; set; }
public string BorrowerMI { get; set; }
public string BorrowerLast { get; set; }
public Suffix? BorrowerSuffix { get; set; }
}
can be reused in another class multiple times.
How can I separate that to strip that and instead use a named class consisting of first, middle and last names and allowing up to four "person" instances in my master class?
Have you tried inheritance?
public class Person
{
public Guid SomeClassId {get; set;}
public string BorrowerFirst { get; set; }
public string BorrowerMI { get; set; }
public string BorrowerLast { get; set; }
public Suffix? BorrowerSuffix { get; set; }
}
and the Applicant class:
public class Applicant : Person
{
//Only extra properties and methods here.
public string FullName
{
get
{
return this.BorrowerFirst + " " + this.BorrowerMI + " " + this.BorrowerLast;
}
}
}
You can then have a vendor as well:
public class Vendor: Person
{
//Only extra properties and methods here.
}
Is there any way to access the Class and Property name which you attached an attribute to inside the attribute?
For example
public class User {
public string Email { get; set; }
public string FirstName { get; set; }
[MyAttribute]
public string LastName { get; set; }
}
And then in the MyAttribute class
public class MyAttributeAttribute {
public MyAttributeAttribute () : base() {
string className = /*GET CLASS NAME - should return "User" */
string propertyName = /*GET PROPERTY NAME - should return LastName*/
}
}
I know I can pass in the information in the constructor, but hoping there is an easy way somehow to save on retyping info over and over again either via reflection or...
Sorry, but no that's not possible. You could also have
public class User {
public string Email { get; set; }
public string FirstName { get; set; }
[MyAttrubute]
public string LastName { get; set; }
}
[MyAttrubute]
public class OtherClass {
[MyAttrubute]
public string AnotherProperty { get; set; }
}
The attribute can be created from anywhere. Even the following is a valid way to create an instance:
var att = new MyAttribute();
Your question could be boiled down to "Can I detect where my custom class is instantiated from?". In my last example, StackTrace could probably be used. But with attributes they are being constructed by the .NET runtime, so you would not be able to go that route.