Autofac - Configure Module List-Property with object - autofac

I want to configure per XML a module with a property, which contains a list of class MyObject.
My Module and MyObject class are looking like:
public class MyModule : Module
{
public IList<MyObject> MyObjects { get; set; }
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
// Do something with MyObjects.
}
}
public class MyObject
{
public string Id { get; set; }
public bool IsVisable { get; set; }
}
My assumption was to configure it like this in XML:
<modules name="MyModule">
<type>...</type>
<properties>
<MyObjects>
<MyObject>
<Id>1234</Id>
<IsVisilble>false</IsVisilble>
</MyObject>
</MyObjects>
</properties>
But if I run this, I get the following exception:
Unable to convert object of type 'Autofac.Configuration.Util.ConfiguredDictionaryParameter' to type 'System.Collections.Generic.IList`1[MyObject]'
I'm using Autofac 4.5.0 with Autofac.Configuration 4.0.1.
What am I doing wrong? Is there a way to get it working?

Related

issue with new create dbcontext class object in asp.net core 2.1

I m new in .net core 2.1
I m working with .net core 2.1 with code first approach
issue is when I create a new object dbcontext class then give error see below line
dbcontextstudent db=new dbcontextstudent(); //here give an red line
appsettings.json
},
"ConnectionStrings": {
"sqlserverconn": "Server=DEVISSHAHID; Database=studdbs; User id=xxxx;Password=xxxxx;"
},
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
//connection string
services.AddDbContext<DbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("sqlserverconn")));
student.cs
namespace WebApplication1.Models
{
public class student
{
[Key]
public int studid { get; set; }
public string studname { get; set; }
public string studsalary { get; set; }
public int studage { get; set; }
}
}
dbcontextstudent.cs
namespace WebApplication1.Models
{
public class dbcontextstudent : DbContext
{
public dbcontextstudent(DbContextOptions<dbcontextstudent> options) : base(options)
{
}
public DbSet<student> stud { get; set; }
}
}
HomeController.cs
I m not understood the above intellisense
I write the code as per intellisense but still give an error I know error is clear but not solved
which place doing I m wrong?
You will have to pass your DbContext type to the AddDbContext method in ConfigureServices method like this:
services.AddDbContext<dbcontextstudent>(options => options.UseSqlServer(Configuration.GetConnectionString("sqlserverconn")));
After that, you have registered the dbcontextstudent class in dependency injection.
You shouldn't create the instance of dbcontextstudent on your own like you did:
dbcontextstudent db=new dbcontextstudent();
Instead you can inject it though the constructor of your controller like this:
public HomeController : Controller
{
private readonly dbcontextstudent _db;
public HomeController(dbcontextstudent db)
{
_db = db;
}
... and then you can use the _db variable in your post action
}

Using Generic Type DTO In ServiceStack Request

I was wondering if it's possible to use a Templated DTO requested of the type public class
RequestDTO<T, U> where T : class where U : class
{
public T ContextRequest { get; set; }
public U Request { get; set; }
}
And pass it to my service's request...
I've tried a simple example of type
public class MyContext
{
//removed some fields
public int IdUser {get;set;}
}
public class MyType1Request
{
public int IdRequest {get;set;}
}
public class MyType2Request
{
public DateTime SomeReallyImportantDate { get; set; }
}
public class UtenteService : Service
{
public UtenteService()
{
}
public string Any(RequestDTO<MyContext,MyType1Request> request)
{
return string.Format("User:{0} - IDRequest: {1}", request.ContextRequest.IdUser, request.Request.IDRequest);
}
public object Any(RequestDTO<MyContext, MyType2Request> request)
{
return string.Format("Utente:{0} - Data : {1}", request.ContextRequest.IDUtente, request.Request.DataLavorativa);
}
But I got this as far I try to access to the service
Sequence contains more than one matching element
Another solution is to implement in each my DTO Request object a IContext (and maybe IContextExt IContextSpecificManner) into the request object...but I would prefer to use the first approach
Thanks
AFAIK - This should work. The only thing that I am missing here is, you need to register route in apphost like:
Routes.Add>("/Utente/{IdUser}/{IdRequest}")

How to use AOP (PostSharp) for Serialization?

Is it possible to inject code to read/write the properties of an object using a PostSharp aspect? For example, consider the following class:
[ BinarySerializable ]
public class Employee {
public string Name {get; set; }
public string Title {get; set;}
}
In this case, "BinarySerializable" would be a custom aspect that introduces a custom "IBinarySerializable" interface, as follows:
public interface IBinarySerializable
{
void Write(BinaryWriter writer);
void Read(BinaryReader reader);
}
After compilation, the resulting class would look like this:
public class Employee : IBinarySerializable
{
public string Name {get; set;}
public string Title {get; set; }
void IBinarySerializable.Write(BinaryWriter writer)
{
writer.Write(Name);
writer.Write(Title);
}
void IBinarySerializable.Read(BinaryReader reader)
{
Name = reader.ReadString();
Title = reader.ReadString();
}
}
Intuitively, I feel this should be possible using PostSharp, but I need some direction as to the right approach. If this is possible, then how to handle properties that are themselves injected by some other aspect?
UPDATE: I tried creating a simple example using the built-in PSerializable aspect, but ran into problems when members inherit from .NET framework classes that do not have that attribute.
Adding the [PSerializable] attribute to the EmployeeCollection class fails to compile with "Cannot apply [PSerializable] to type 'AOPSerialization.EmployeeCollection' because the base type does not have a [PSerializable] or [Serializer] attribute."
Omitting the [PSerializable] attribute from the EmployeeCollection class throws a runtime PortableSerializationException: Cannot find a serializer for type 'AOPSerialization.EmployeeCollection'.
For example:
[PSerializable]
public class AOPComponent
{
public string Title { get; set; }
public string Description { get; set; }
public AOPComponent(string title, string description){...}
}
[PSerializable]
public class AOPComponentCollection<T> : ObservableCollection<T>
{...}
[PSerializable]
public class EmployeeCollection : AOPComponentCollection<Employee>
{...}
[PSerializable]
public class Company : AOPComponent
{
public EmployeeCollection Engineers { get; set; }
public EmployeeCollection Managers { get; set; }
}
I figured out that the Serializer and ImportSerializer attributes are used to tell the PortableFormatter which custom ISerializer or ISerializerFactory implementation to use.
But the question remains:
How to specify a custom serializer for the generic base collection type?
This approach fails because an attribute may not include type parameters.
[PSerializable, ImportSerializer(typeof(ObservableCollection<T>), typeof(AOPComponentSerializerFactory))]
public class AOPComponentCollection<T> : ObservableCollection<T> where T : AOPComponent
{...}
This approach fails because PostSharp cannot find a serializer for ObservableCollection< T >
[PSerializable, Serializer(typeof(AOPComponentSerializerFactory))]
public class AOPComponentCollection<T> : ObservableCollection<T> where T : AOPComponent
{...}
It would be possible to do that with PostSharp, but only by using the low-level PostSharp SDK, which is undocumented and unsupported.
Good news are that we already implemented this for you, in the namespace PostSharp.Serialization. The aspect is [PSerializable] and the formatter is PortableFormatter.

MEF imports with metadata not matching any exports

I have been trying to use MEF on a new project and am having some difficulty getting imports to work, which I cannot explain why. I am following the samples on MSDN and elsewhere, but they are not working for me. This is using MEF 4.0 in a .NET 4 project.
I have defined a simple contract:
public interface ICommand
{
int Execute(string[] args);
}
I implemented some parts and added some metadata:
[Export(typeof(ICommand))]
[ExportMetadata("Name", "init")]
public class InitCommand : ICommand { ... }
[Export(typeof(ICommand))]
[ExportMetadata("Category", "service")]
[ExportMetadata("Name", "start")]
public class StartServiceCommand : ICommand { ... }
I defined the following metadata interface:
public interface ICommandMetadata
{
[DefaultValue(null)]
string Category { get; }
string Name { get; }
}
In my main program, I am creating a catalog-based export provider and then trying to compose the main program object:
internal class Program
{
[ImportMany]
private IEnumerabe<Lazy<ICommand, ICommandMetadata>> commands;
private static int Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyExportProvider = new CatalogExportProvider(new AssemblyCatalog(assembly));
var compositionContainer = new CompositionContainer(assemblyExportProvider);
assemblyExportProvider.SourceProvider = compositionContainer;
var batch = new CompositionBatch();
batch.AddPart(this);
compositionContainer.Compose(batch);
return 0;
}
}
When I run the above code, this works as expected and both parts are resolved. When I go a step further and create a custom export attribute, the code stops working. Here's my custom metadata attribute and updated parts:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
[MetadataAttribute]
public sealed class CommandAttribute : ExportAttribute
{
public CommandAttribute() : base(typeof(ICommand))
{
}
[DefaultValue(null)]
public string Category { get; set; }
public string Name { get; set; }
}
[Command(Name = "init")]
public class InitCommand : ICommand { ... }
[Command(Category = "service", Name = "start")]
public class StartServiceCommand : ICommand { ... }
By applying the custom export attribute, my commands collection in my program is an empty array. I played around with this some more, and I found that if I change the properties in the metadata interface to arrays of strings, the importing works again:
public interface ICommandMetadata
{
[DefaultValue(null)]
string[] Category { get; }
string[] Name { get; }
}
Can anyone tell me if I am doing something wrong? Why does this only work if I use arrays in the metadata interface? Is there a way to make this work without using arrays for the properties?
Thanks in advance for your help.

Schema invalid and types cannot be loaded because the assembly contains EdmSchemaAttribute

Getting the following error:
Schema specified is not valid. Errors:
The types in the assembly 'x, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null' cannot be loaded because the assembly contains
the EdmSchemaAttribute, and the closure of types is being loaded by
name. Loading by both name and attribute is not allowed.
What does this error mean exactly?
I'm trying to shoe-horn into my application an EF model from an existing database.
Before this application was based on CodeFirst and using the repository pattern but for the life of me I can't get this working.
Before I had:
public class BaseModelContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
}
But in a EF model-first scenario (one where tables already exist in the db), I had to remove these as it didn't seem to like having a repository pattern on DbSet properties.
So I stripped these out, and the repository can then use repository on the classes already defined on the .designer.cs context class (the EF model). This has the EdmSchemaAttribute set inside the generated code.
So how do I get my repository pattern to work in the model-first scenario? What does the above error mean exactly?
EDIT
Added new code:
public class BaseModelContext : DbContext
{
// public DbSet<Location> Locations { get; set; }
public BaseModelContext(string nameOrConnection)
: base(nameOrConnection)
{
}
public BaseModelContext()
{
}
}
public class VisitoriDataContext : BaseModelContext
{
public VisitoriDataContext()
: base("visitoriDataConnection")
{
}
}
public interface IVisitoriDataContextProvider
{
VisitoriDataContext DataContext { get; }
}
public class VisitoriDataContextProvider : IVisitoriDataContextProvider
{
public VisitoriDataContext DataContext { get; private set; }
public VisitoriDataContextProvider()
{
DataContext = new VisitoriDataContext();
}
}
public class VisitoriRepository<T> : IRepository<T> where T : class
{
protected readonly IVisitoriDataContextProvider _ctx;
public VisitoriRepository(IVisitoriDataContextProvider ctx)
{
_ctx = ctx;
}
public T Get(int id)
{
return _ctx.DataContext.Set<T>().Find(id);
}
}
public interface ILocationRepo : IRepository<Location>
{
IEnumerable<Location> GetSuggestedLocationsByPrefix(string searchPrefix);
}
public class LocationRepo : VisitoriRepository<Location>, ILocationRepo
{
public LocationRepo(IVisitoriDataContextProvider ctx)
: base(ctx)
{
}
public IEnumerable<Location> GetSuggestedLocationsByPrefix(string searchPrefix)
{
return Where(l => l.name.Contains(searchPrefix)).ToList();
}
}
The error means that you cannot combine code first mapping (data annotations and fluent API) and EDMX mapping (with EntityObjects!) for entity with the same name. These two approaches are disjunctive.
The rest of your question is not clear.
Btw. building mapping from existing database is called database first not model first.
Decorate the assembly containing the GILayerModel type with [assembly: EdmSchema] attribute.
In my case, I had a class that derived from an entity (code-first class) in another assembly, and I was adding an instance of this class to the DBContext:
in DBEntities project:
public class GISLayer
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int GISLayerId { get; set; }
[StringLength(200)]
public string LayerName { get; set; }
public List<GISNode> Nodes { get; set; }
}
in the second assembly:
public class GISLayerModel : DBEntities.GISLayer
{
public new List<GISNodeModel> NodesModel { get; set; }
}
and the cause of error:
[WebMethod]
public void SaveGISLayers(GISLayerModel[] layers)
{
using (DBEntities.DBEntities db = new DBEntities.DBEntities())
{
foreach (var l in layers)
{
if (l.GISLayerId > 0)
{
db.GISLayers.Attach(l); //attaching a derived class
db.Entry(l).State = System.Data.EntityState.Modified;
}
else
db.GISLayers.Add(l); //adding a derived class
SaveGISNodes(l.NodesModel.ToArray(), db);
}
db.SaveChanges();
}
}
So, I used AutoMapper to copy properties of derived class to a new instance of base class:
DBEntities.GISLayer gl = AutoMapper.Mapper.Map<DBEntities.GISLayer>(l);
if (gl.GISLayerId > 0)
{
db.GISLayers.Attach(gl);
db.Entry(gl).State = System.Data.EntityState.Modified;
}
else
db.GISLayers.Add(gl);
That solved the problem.