I've created a custom attribute which writes to the console when it's hit, however it doesn't seem to be hit. It's the microsoft tutorial (http://msdn.microsoft.com/en-us/library/sw480ze8.aspx) and is being run on 2010, .net 4. I'm guessing it must be me that's doing something wrong, but I can't see what it is. Can anyone help?
This is the attribute, whose code is never being hit
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class Author : Attribute
{
private string _name;
private double _version;
public Author(string name)
{
Console.WriteLine(string.Format("author {0} was just created", name));
_name = name;
_version = 1.0;
}
}
This is the class that uses it - it's successfully writing out the code in the constructor:
/// <summary>
/// TODO: Update summary.
/// </summary>
[Author("P. Ackerman")]
public class Ackerman
{
public Ackerman()
{
Console.WriteLine("I created Ackerman.");
}
}
And this is the console app that calls it and is successfully printing out the code in the new Ackerman() constructor:
static void Main(string[] args)
{
Ackerman author1 = new Ackerman();
Console.ReadLine();
}
Thanks!!
Instances of attributes on class are not created then you create instance of class. Only then you specifically asks for them like this:
var attrib = author1.GetType().GetCustomAttributes(false);
This code will trigger your Console.WriteLine(string.Format("author {0} was just created", name));
Related
I have taken the MixedType example code that comes with the java stream client (https://github.com/GetStream/stream-java) and added a update step using updateActivities. After the update the activity stored in stream loses the 'type' attribute. Jackson uses this attribute when you get the activities again and it is deserialising them.
So I get:
Exception in thread "main" Disconnected from the target VM, address: '127.0.0.1:60016', transport: 'socket'
com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id 'null' into a subtype of [simple type, class io.getstream.client.apache.example.mixtype.MixedType$Match]
at [Source: org.apache.http.client.entity.LazyDecompressingInputStream#29ad44e3; line: 1, column: 619] (through reference chain: io.getstream.client.model.beans.StreamResponse["results"]->java.util.ArrayList[1])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
at com.fasterxml.jackson.databind.DeserializationContext.unknownTypeException(DeserializationContext.java:849)
See here where I have updated the example:
https://github.com/puntaa/stream-java/blob/master/stream-repo-apache/src/test/java/io/getstream/client/apache/example/mixtype/MixedType.java
Any idea what is going on here?
The issue here is originated by Jackson which cannot get the actual instance type of an object inside the collection due to the Java type erasure, if you want to know more about it please read this issue: https://github.com/FasterXML/jackson-databind/issues/336 (which also provides some possible workarounds).
The easiest way to solve it, would be to manually force the value of the property type from within the subclass as shown in the example below:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
#JsonSubTypes({
#JsonSubTypes.Type(value = VolleyballMatch.class, name = "volley"),
#JsonSubTypes.Type(value = FootballMatch.class, name = "football")
})
static abstract class Match extends BaseActivity {
private String type;
public String getType() {
return type;
}
}
static class VolleyballMatch extends Match {
private int nrOfServed;
private int nrOfBlocked;
public VolleyballMatch() {
super.type = "volley";
}
public int getNrOfServed() {
return nrOfServed;
}
public void setNrOfServed(int nrOfServed) {
this.nrOfServed = nrOfServed;
}
public void setNrOfBlocked(int nrOfBlocked) {
this.nrOfBlocked = nrOfBlocked;
}
public int getNrOfBlocked() {
return nrOfBlocked;
}
}
static class FootballMatch extends Match {
private int nrOfPenalty;
private int nrOfScore;
public FootballMatch() {
super.type = "football";
}
public int getNrOfPenalty() {
return nrOfPenalty;
}
public void setNrOfPenalty(int nrOfPenalty) {
this.nrOfPenalty = nrOfPenalty;
}
public int getNrOfScore() {
return nrOfScore;
}
public void setNrOfScore(int nrOfScore) {
this.nrOfScore = nrOfScore;
}
}
I have a Person and a PersonViewModel. I created a map from Person => PersonViewModel. The problem is that PersonViewModel's only constructor needs an argument (it has a dependency that I want to be injected) and AutoMapper is complaining because it says it needs a parameterless constructor.
To fix it, I used the ConstructServicesUsing method, but I haven't been successful with it :(
To illustrate the case, I created a test for you to see what I'm doing. It's pretty simple:
[TestMethod]
public void TestConstructServicesUsing()
{
Mapper.Initialize(configuration =>
{
configuration.ConstructServicesUsing(FactoryMethod);
configuration.CreateMap<Person, PersonViewModel>();
});
Mapper.AssertConfigurationIsValid();
var person = new Person();
var personViewModel = Mapper.Map<Person, PersonViewModel>(person);
}
private object FactoryMethod(Type type)
{
throw new NotImplementedException();
}
}
The rest of the code is the classes and interface definitions. They are almost empty.
public class SomeyDependency : ISomeDependency
{
}
public class PersonViewModel
{
private readonly ISomeDependency service;
public PersonViewModel(ISomeDependency service)
{
this.service = service;
}
public string Name { get; set; }
}
public class Person
{
public string Name { get; set; }
}
public interface ISomeDependency
{
}
As you see, I provide AutoMapper with a FactoryMethod, but it never get called.
When it reaches the last line of the test (Mapper.Map<...>()) it throws an excepton saying:
AutoMapper.AutoMapperMappingException:
Mapping types:
Person -> PersonViewModel
MappingWithContainerTests.Person -> MappingWithContainerTests.PersonViewModel
Destination path:
PersonViewModel
Source value:
MappingWithContainerTests.Person ---> System.ArgumentException: Type needs to have a constructor with 0 args or only optional args
Parameter name: type
What's the problem?
Why isn't the FactoryMethod being called?
As #khorvat mention where is missing .ConstructUsingServiceLocator(), for concrete mapping.
Also you can set constructor directly by
.ConstructUsing(source => Method(source.anySourceOptions))
Or as exception said:
PersonViewModel, must have a constructor with 0 args or only optional
args. You have only one constructor with 1 not optional argument
you may create one more constructor without args:
public PersonViewModel()
{
this.service = new SomeDependency();
}
I'm using .NET Core 3.1 and Automapper.Extensions.Microsoft.DependencyInjection.
This does not work for me (Same error as yours):
public class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<Context, MainViewModel>()
.ReverseMap()
.ConstructUsingServiceLocator();
}
}
But this does work:
public class AutoMapping : Profile
{
public AutoMapping()
{
CreateMap<Context, MainViewModel>()
.ConstructUsingServiceLocator()
.ReverseMap();
}
}
I still do not fully understand the cause.
I've been bumbling along with EF5 but I cant seem to get two domain classes to map to a single database table.
The error I get is:
Message: "The type 'Basd.Erp.Wms.Purchasing.SupplierProfile' has already been configured as an entity type. It cannot be reconfigured as a complex type."
This is my DbContext:
public class PurchasingContext : DisconnectedEntityContext
{
public DbSet<SupplierCard> Suppliers { get; set; }
public DbSet<PurchaseCategory> PurchaseCategories { get; set; }
public PurchasingContext() : this("Basd.Erp.Wms") { }
public PurchasingContext(string connectionStringName) : base(connectionStringName) { }
public static PurchasingContext GetInstance(EfDataProvider provider) { return new PurchasingContext(provider.ConnectionStringName); }
}
}
These are my classes:
namespace Basd.Erp.Wms.Purchasing
{
public class SupplierCard : ContactCard, ISupplierCard
{
private ICollection<PurchaseCategory> _purchaseCategories;
public ICollection<PurchaseCategory> PurchaseCategories
{
get { return _purchaseCategories; }
set { SetNotifyField(ref _purchaseCategories, value, () => PurchaseCategories); }
}
public SupplierProfile Profile { get; protected set; }
private SupplierCard()
{
this.Profile = new SupplierProfile();
this.PurchaseCategories = new Collection<PurchaseCategory>();
}
public SupplierCard(long id, string alf, string name)
: this(id, alf, new SimpleNameHolder(name), new Collection<IPhysicalAddress>(), new DigitalAddresses()) { }
public SupplierCard(long id, string alf, INameHolder nameHolder,
ICollection<IPhysicalAddress> physicalAddresses, IDigitalAddresses digitalAddresses)
: this(id, alf, nameHolder, physicalAddresses, digitalAddresses, null) { }
public SupplierCard(long id, string alf, INameHolder nameHolder,
ICollection<IPhysicalAddress> physicalAddresses, IDigitalAddresses digitalAddresses, IValidatableObject validator)
: base(id, alf, nameHolder, physicalAddresses, digitalAddresses, validator)
{
this.Profile = new SupplierProfile();
this.PurchaseCategories = new Collection<PurchaseCategory>();
}
}
}
public class SupplierProfile : AbstractAspect
{
private TradingEntity _incType;
public TradingEntity BusinessType
{
get { return _incType; }
set
{
if (_incType != null) { this.DeregisterSubPropertyForChangeTracking(this.BusinessType); }
_incType = value; this.OnPropertyChanged("TradingType");
this.RegisterSubPropertyForChangeTracking(this.BusinessType);
}
}
private bool _emailOk;
private bool _smailOk;
public bool MarketingEmailOk
{
get { return _emailOk; }
set { _emailOk = value; this.OnPropertyChanged("MarketingEmailOk"); }
}
public bool MarketingSmailOk
{
get { return _smailOk; }
set { _smailOk = value; this.OnPropertyChanged("MarketingSmailOk"); }
}
public SupplierProfile()
: base()
{
this.BusinessType = new TradingEntity(ContactLegalType.Limited);
}
}
}
These are my configuration classes:
[Export(typeof(IEntityConfiguration))]
public class SupplierCardConfiguration
: EntityTypeConfiguration<SupplierCard>, IEntityConfiguration
{
public SupplierCardConfiguration()
{
this.ToTable("SupplierCard", "erp_wms");
HasKey(u => u.Id);
Property(u => u.Id).HasColumnName("SupplierId");
Ignore(u => u.UsePropertyNotifications);
Property(u => u.Profile.MarketingEmailOk).HasColumnName("MarketingEmailOk");
HasMany(i => i.PurchaseCategories)
.WithMany(c => c.Suppliers)
.Map(mc =>
{
mc.MapLeftKey("CategoryId");
mc.MapRightKey("SupplierId");
mc.ToTable("SupplierPurchaseCategory", "erp_wms");
});
}
public void AddConfiguration(ConfigurationRegistrar registrar)
{
registrar.Add(this);
}
}
[Export(typeof(IEntityConfiguration))]
public class SupplierProfileConfiguration
: EntityTypeConfiguration<SupplierProfile>, IEntityConfiguration
{
public SupplierProfileConfiguration()
{
this.ToTable("SupplierCard", "erp_wms");
Ignore(u => u.UsePropertyNotifications);
Property(u => u.MarketingEmailOk).HasColumnName("MarketingEmailOk");
}
public void AddConfiguration(ConfigurationRegistrar registrar)
{
registrar.Add(this);
}
}
UPDATE:
Ok so Ive tried ignoring SupplierProfile as per suggestion that changed nothing. I then tried removing the configuration class for Supplier Profile and left
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<SupplierProfile>();
base.OnModelCreating(modelBuilder);
}
and that generated an error:
{"The property 'Profile' is not a declared property on type
'SupplierCard'. Verify that the property has not been explicitly
excluded from the model by using the Ignore method or
NotMappedAttribute data annotation. Make sure that it is a valid
primitive property."}
[System.InvalidOperationException]: {"The property 'Profile' is not a declared property on type 'SupplierCard'. Verify that the
property has not been explicitly excluded from the model by using the
Ignore method or NotMappedAttribute data annotation. Make sure that it
is a valid primitive property."}
I then tried removing the
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<SupplierProfile>();
base.OnModelCreating(modelBuilder);
}
while leaving out the configuration class for SupplierProfile and that generates the error:
Message: "Invalid column name
'Profile_BusinessType_ContactLegalType'.\r\nInvalid column name
'Profile_BusinessType_TradingSince'.\r\nInvalid column name
'Profile_BusinessType_State'.\r\nInvalid column name
'Profile_BusinessType_UsePropertyNotifications'.\r\nInvalid column
name 'MarketingEmailOk'.\r\nInvalid column name
'Profile_MarketingSmailOk'.\r\nInvalid column name
'Profile_State'.\r\nInvalid column name
'Profile_UsePropertyNotifications'.\r\nInvalid column name
'OwnerId'.\r\nInvalid column name 'State'."
So like I said, just **bumbling** along ;)
After reading this I think it might have something to do with your relationship in your SupplierCard class.
public class SupplierCard : ContactCard, ISupplierCard
{
public SupplierProfile Profile { get; protected set; }
}
I'm guessing it registering as a complex type when SupplierCard is mapped.
A suggested way to fix it is to ignore it.
modelBuilder.Ignore<SupplierProfile>();
I've never run into this problem myself, so not sure if this'll help.
So after a lot of mucking around it turns out the underlying problem is a bug in Entity Framework 5. This bug has been fixed in EF6 beta. All other errors were in fact just masking this underlying error.
The following explaination is not terribly good as I dont fully understand it myself.
Short answer is: Use EF6 or otherwise modify EF5 source code.
Turns out that if you have a class in assembly B, that has a property of a type of enum defined in Assembly A, EF5 gets confused and thinks the enum is missing or somehow unavailable and sets about trying to generate the type itself.
So I had:
Assembly A containing enum type AA.
Assembly B referencing Assembly A so a contained class BB could have a property of type AA.
An EF5 data layer Assembly referencing both Assembly A & B.
An EF5 configuration layer Assembly referencing both Assembly A & B.
And it failed.
But if I "simply" move enum type AA into Assembly B then everything works.
This is of course is completely useless because then I set up all kinds of dependencies on Assembly B for any Assembly that has a member who needs an enum AA. But that is the test.
To top it off there also appears to be some particular set of circumstances in which everything I just said does not apply due to the order assemblies are loaded at runtime. The order of this loading cannot be forced i.e. it's non-determinant so it's pot luck.
Given this class:
class Foo
{
readonly ILog log;
public Foo(ILog log)
{
this.log = log;
}
...
}
I'd like to configure Unity to inject ILog. That's easy:
container.RegisterInstance<ILog>(LogManager.GetLogger(typeof(XYZ)));
But I'd like to make Unity call LogManager.GetLogger with the type of the parent type being resolved.
This is close:
container.RegisterType<ILog>(new InjectionFactory((c, t, s) => LogManager.GetLogger(t)));
But t in this case is the type being resolved (ILog), not the type that the object is being resolved for (Foo).
I know I can do this:
container.RegisterType<Foo>(new InjectionFactory(c => new Foo(LogManager.GetLogger(typeof(Foo)));
But I don't want to have to add that crazy declaration every time I register an object.
I know this can be done in Autofac, and I know the Real Answer is not to use Unity in the first place, but can this be done? :)
Unity might not give you all the goodies some of the other containers offer but I have yet to find a feature you can't easily add.
var container = new UnityContainer();
container.AddNewExtension<TrackingExtension>();
container.RegisterType<ILog>(
new InjectionFactory((ctr, type, name) =>
{
var tracker = ctr.Resolve<ITracker>();
var parentType = tracker.CurrentBuildNode.Parent.BuildKey.Type;
return LogManager.GetLogger(parentType);
}));
var sut = container.Resolve<UsesLog>();
Assert.AreEqual(typeof(UsesLog), sut.Log.Type);
You can find the source code for the TrackingExtension here. Its located in the TecX.Unity project folder.
If you want a DI container to return you a logger based on the class’ type information, then put the type information into the public interface so the DI container can see it. It removes the need for any container specific override features and then it won’t matter if you are using Unity or AutoFac.
Someone that knows the log4net object model well might be able to give you a more efficient implementation, but try something like this:
using System;
using Microsoft.Practices.Unity;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UnityLoging
{
public interface ILog<T> : log4net.ILog
{ }
public class MyLogger<T> : log4net.Core.LogImpl, ILog<T>
{
public MyLogger() : base(log4net.LogManager.GetLogger(typeof(T).Name).Logger)
{ }
}
public class ClassToLog
{
private readonly log4net.ILog log;
public ClassToLog(ILog<ClassToLog> log)
{
this.log = log;
}
public void LogMe()
{
log.Debug("Got here");
}
}
[TestClass]
public class TestClass
{
[TestMethod]
public void GenericLogRegistrationTest()
{
log4net.Config.XmlConfigurator.Configure();
IUnityContainer container = new UnityContainer();
container.RegisterType(typeof(ILog<>), typeof(MyLogger<>));
ClassToLog c = container.Resolve<ClassToLog>();
c.LogMe();
log4net.LogManager.Shutdown();
}
}
}
This seems like a very clean approach: https://github.com/roblevine/UnityLoggingExtensions
I'm attempting to use the SimpleRepository to perform a fetch based on a non-ID property. Here's the Customer class I'm using:
[Serializable]
public class Customer : IEntity<Guid>
{
public Guid ProviderUserKey { get; set; }
public Guid ID
{
get; set;
}
}
I'm using SimpleRepository with migrations turned on. The code that throws the "Lambda Parameter not in scope" is below:
public class CustomerRepository :
ICustomerRepository
{
private readonly IRepository _impl;
public CustomerRepository(string connectionStringName)
{
_impl = new SimpleRepository(connectionStringName,
SimpleRepositoryOptions.RunMigrations);
}
public Customer GetCustomer(string userName)
{
var user = Membership.GetUser(userName);
// Code to guard against a missing user would go here
// This line throws the exception
var customer = _impl.Single<Customer>(c => c.ProviderUserKey.Equals(user.ProviderUserKey));
// Code to create a new customer based on the
// ASP.NET Membership user would go here
return customer;
}
}
I'm not sure at what point in the LINQ expression compilation this throws, but I am running this example on an empty database. The schema generations gets far enough to create the table structure, but can't evaluate the expression.
Does anyone know what I might be doing wrong?
Thanks!
I've had reports of this - can you add this (and your code) as an issue please?