Test code looks something like this
if (table.ContainsColumn("DecisionGroupOptionId"))
{
foreach (var tableRow in table.Rows)
{
try
{
var name = tableRow["DecisionGroupOptionId"];
var code = _catalogLookupContext.DecisionGroupOptions.FindIdByName(name);
tableRow["DecisionGroupOptionId"] = code;
}
catch (Exception)
{
//don't fail
}
}
}
public virtual string FindIdByName(string name)
{
var item = _list.FirstOrDefault(r => r.Name == name);
Assert.That(item, Is.Not.Null, "ID lookup by the name '{0}' failed. No such name exists in the map.", name);
return item.Id;
}
Testlog output :
Failed : org.test.Test.Silverthread.test1
ID lookup by the name '' failed. No such name exists in the map.
Expected: not null
But was: null
at org.test.Test.SilverThread.FindIdByName(String name) in IdLookup.cs:line
160
The testlog shows failure if 'name' is null.
Isnt this not supposed to show failure as there is catch block? Please help.
Test project uses assemblies like below
[SpecFlow] SpecFlow.Tools.MsBuild.Generation, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
[SpecFlow] TechTalk.SpecFlow, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
[SpecFlow] TechTalk.SpecFlow.Generator, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
[SpecFlow] TechTalk.SpecFlow.Utils, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
[SpecFlow] TechTalk.SpecFlow.Parser, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
[SpecFlow] TechTalk.SpecFlow.NUnit.Generator.SpecFlowPlugin, Version=3.1.0.0, Culture=neutral, PublicKeyToken=0778194805d6db41
Related
I'm working on xamarin.android and I get this error when a package downloaded a dependent package with existing class
public class DeliveriesFragment : Android.Support.V4.App.ListFragment
{
public override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
}
as you can see I fully typed the class with its namespace
Android.Support.V4.App.ListFragment
but I still get this error
The type 'ListFragment' exists in both 'Xamarin.Android.Support.Fragment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' and 'Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
any idea how to fix this? thanks
Good evening everyone.
Currently, I'm new person in IoC/DI. I have a Winform project with C#. Please view some codes and help me resolve below issue:
1/ IRepository
namespace Framework.Repositories
{
public interface IRepository<T> : IDisposable where T:class
{
T Get(int id);
IEnumerable<T> GetAll();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
}
2/ Repository
namespace Framework.Repositories
{
public class Repository<T> : IRepository<T> where T : class
{
private bool _disposed = false;
private static bool _isTransactionStarted;
protected readonly DbContext Context;
private DbContextTransaction _transaction { get; set; }
public Repository(DbContext context)
{
Context = context;
_isTransactionStarted = false;
if (context == null)
throw new NullReferenceException(nameof(context));
if (Context.Set<T>() == null)
throw new NullReferenceException("_context.Set<T>()");
}
public T Get(int id) => Context.Set<T>().Find(id);
public IEnumerable<T> GetAll() => Context.Set<T>().ToList();
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate) => Context.Set<T>().Where(predicate);
}
}
3/ Model
namespace PRO.Model
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("Employee")]
public partial class Employee
{
[Key]
public long EmpId { get; set; }
[StringLength(15)]
public string Username { get; set; }
public string Password { get; set; }
[StringLength(50)]
public string UserGroup { get; set; }
[Required]
[StringLength(50)]
public string FirstName { get; set; }
[StringLength(50)]
public string LastName { get; set; }
[Required]
[StringLength(1)]
public string EmpStatus { get; set; }
}
}
4/ IEmployeeRepository
namespace PRO.Repositories
{
public interface IEmployeeRepository:IRepository<Employee>
{
Employee UserLogin(string username, string password);
}
}
5/ EmployeeRepository
namespace PRO.Repositories
{
public class EmployeeRepository : Repository<Employee>,IEmployeeRepository
{
public EmployeeRepository(DbContext context) : base(context)
{
}
public Employee UserLogin(string username, string password)
{
try
{
return Find(x=>x.Username == username && x.Password == password && x.EmpStatus == BooleanType.Yes ).FirstOrDefault();
}
catch (Exception ex)
{
throw new RepositoryException(ex);
}
}
public MyDbContext myDbContext => Context as MinhTamHotelDbContext;
}
}
6/ IEmployeeService
namespace PRO.Services
{
public interface IEmployeeService
{
Employee UserLogin(string username, string password);
}
}
7/ EmployeeService
namespace PRO.Services
{
public class EmployeeService : IEmployeeService
{
public IEmployeeRepository EmployeeRepos { get; set; }
public Employee UserLogin(string username, string password)
{
return EmployeeRepos.UserLogin(username, password);
}
}
}
8/ DbContext
namespace PRO.Repositories
{
using System.Data.Entity;
public partial class MyHotelDbContext: DbContext
{
public MyHotelDbContext()
: base("name=MyHotelDbContext")
{
}
public virtual DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//DbContext Here
}
}
}
9/App.config
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<connectionStrings>
<add name="MinhTamHotelDbContext" connectionString="data source=.;initial catalog=WiF;persist security info=True;user id=sa;password=#success#;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
<alias alias="transient" type="Microsoft.Practices.Unity.TransientLifetimeManager, Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<alias alias="perResolve" type="Microsoft.Practices.Unity.PerResolveLifetimeManager, Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<alias alias="singleton" type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity, Version=2.1.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<alias alias="AreaRepository" type="PRO.Repositories.AreaRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IAreaRepository" type="PRO.Repositories.IAreaRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="EmployeeRepository" type="PRO.Repositories.EmployeeRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IEmployeeRepository" type="PRO.Repositories.IEmployeeRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="GnrlCodeRepository" type="PRO.Repositories.GnrlCodeRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IGnrlCodeRepository" type="PRO.Repositories.IGnrlCodeRepository, PRO.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="AreaService" type="PRO.Services.AreaService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IAreaService" type="PRO.Services.IAreaService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="EmployeeService" type="PRO.Services.EmployeeService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IEmployeeService" type="PRO.Services.IEmployeeService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="GnrlCodeService" type="PRO.Services.GnrlCodeService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IGnrlCodeService" type="PRO.Services.IGnrlCodeService, PRO.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="IRepository" type="Framework.Repositories.IRepository, Framework.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<alias alias="Repository" type="Framework.Repositories.Repository, Framework.Repositories, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<container>
<register type="IAreaRepository" mapTo="AreaRepository">
<lifetime type="perResolve" />
</register>
<register type="IEmployeeRepository" mapTo="EmployeeRepository">
<lifetime type="perResolve" />
</register>
<register type="IGnrlCodeRepository" mapTo="GnrlCodeRepository">
<lifetime type="perResolve" />
</register>
<register type="IEmployeeService" mapTo="EmployeeService">
<property name="EmployeeRepos" dependencyType="IEmployeeRepository" />
<lifetime type="perResolve" />
</register>
<register type="IGnrlCodeService" mapTo="GnrlCodeService">
<property name="GnrlCodeRepos" dependencyType="IGnrlCodeRepository" />
<lifetime type="perResolve" />
</register>
<register type="IAreaService" mapTo="AreaService">
<property name="AreaRepos" dependencyType="IAreaRepository" />
<lifetime type="perResolve" />
</register>
</container>
10/ In my login form
public partial class UserLogin : Form
{
private IEmployeeService _employeeSvr = null;
public IEmployeeService EmployeeSrv
{
get { return _employeeSvr ?? (_employeeSvr = UnityInstanceProvider.CreateInstance<IEmployeeService>()); }
set { _employeeSvr = value; }
}
private void btnLogin_Click(object sender, System.EventArgs e)
{
try
{
this.Cursor = Cursors.WaitCursor;
var employee = EmployeeSrv.UserLogin(txtUsername.Text.TrimEx(), txtPassword.Text.TrimEx());
//MsgBox.ShowInfoMsg(employee.ToJsonObject().ToStringEx());
if (employee != null)
{
Visible = false;
AreaMap.Instance.Show();
}
}
catch (Exception ex)
{
ex.ExceptionHandler();
}
finally
{
this.Cursor = Cursors.Default;
}
}
}
My Error is:
Resolution of the dependency failed, type = "PRO.Services.IEmployeeService", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type DbConnection does not have an accessible constructor.
-----------------------------------------------
At the time of the exception, the container was:
Resolving PRO.Services.EmployeeService,(none) (mapped from PRO.Services.IEmployeeService, (none))
Resolving value for property EmployeeService.EmployeeRepos
Resolving PRO.Repositories.EmployeeRepository,(none) (mapped from PRO.Repositories.IEmployeeRepository, (none))
Resolving parameter "context" of constructor PRO.Repositories.EmployeeRepository(System.Data.Entity.DbContext context)
Resolving System.Data.Entity.DbContext,(none)
Resolving parameter "existingConnection" of constructor System.Data.Entity.DbContext(System.Data.Common.DbConnection existingConnection, System.Data.Entity.Infrastructure.DbCompiledModel model, System.Boolean contextOwnsConnection)
Resolving System.Data.Common.DbConnection,(none)
Somebody can help me resolve this problem ?
In case Unity doesn't support multiple inheritance (EmployeeRepository: Repository, IEmployeeRepository), Have another way to replace Unity ?
Thank you so much
I've got this type that's injected with an IFoo:
class MainThing
{
public MainThing(IFoo foo)
{
Console.WriteLine(foo.Name);
}
}
... and this interface:
interface IFoo
{
string Name { get; }
}
... and these two implementations of IFoo:
class Foo1 : IFoo
{
public string Name { get { return #"Foo1"; } }
}
class Foo2 : IFoo
{
public string Name { get { return #"Foo2"; } }
}
... and I've got this StructureMap registration:
var c = new Container(e =>
{
e.AddRegistry<Registry1>();
e.AddRegistry<Registry2>();
e.For<IFoo>().Use<Foo1>();
});
class Registry1 : Registry
{
public Registry1() { For<IFoo>().Use<Foo1>(); }
}
class Registry2 : Registry
{
public Registry2() { For<IFoo>().Use<Foo2>(); }
}
When I called c.GetInstance<MainThing>();, I was expecting MainThing to be given a Foo1 instance, but it's given a Foo2 instance.
The documentation says that subsequent AddRegistry calls overwrite the default instances declared in prior registries. I assumed that because I appended a .Use<Foo1> at the end, that it'd trump everything else before it, but it's not.
Here's WhatDoIHave():
===========================================================================================================
Configuration Sources:
0) Registry: StructureMap.ConfigurationExpression, StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223
1) Registry: ConsoleApplication13.Registry1, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
2) Registry: ConsoleApplication13.Registry2, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
3) Registry: StructureMap.Configuration.DSL.Registry, StructureMap, Version=2.6.4.0, Culture=neutral, PublicKeyToken=e60ad81abae3c223
===============================================================================================================================================================================================================
PluginType Name Description
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Func`1<TResult> (Func`1<TResult>)
Scoped as: Transient
478e77e8-ff84-47e2-bdc1-b90bac2e7b61
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IFoo (ConsoleApplication13.IFoo) f10f7750-f009-4842-ae35-7af47826ac2b Configured Instance of ConsoleApplication13.Foo2, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Scoped as: Transient
9bd57a90-9c1e-4674-b249-7e6e96b40945 Configured Instance of ConsoleApplication13.Foo1, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
3e14df0c-da47-40e2-96ed-9bc6027a5da8 Configured Instance of ConsoleApplication13.Foo1, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
f10f7750-f009-4842-ae35-7af47826ac2b Configured Instance of ConsoleApplication13.Foo2, ConsoleApplication13, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
IContainer (StructureMap.IContainer) cb17947d-5814-4c9b-a219-f359333d6fdb Object: StructureMap.Container
Scoped as: Transient
cb17947d-5814-4c9b-a219-f359333d6fdb Object: StructureMap.Container
===============================================================================================================================================================================================================
Foo2
I can see there's 3 instances of IFoo and that Foo2 is the default, but I don't know why.
Does StructureMap give AddRegistry priority over For?
I think this is correct:
When I instantiate a new Container( e=> ... ), I get the default registry.
I then add two registries, of which both overwrite any configuration if the default registry.
I then change something in the default registry, but this has already been overwritten when adding Registry2.
I've got my claims set-up with MVC3 using azure and everything is going well.
What I need to do now is extend the Claims Identity that's in the current thread / http context and add my own information (DOB, Address.. that sort of stuff)
so my question is - where is the best place to do this? any examples would be great..
I presume that when the user is authenticated id then have to go to the DB and pull back the relevant record for the user then add it to the custom Claims Identity object?
Typically you will have a httpmodule that will inspect the cookies and once the FedAuth token is found, you have a hook to build your Claims Principal and identities.
You don't typically need to store the user's entire profile, just useful things that wont typically change that often. I do this inside of an actionfilter.
Here is the code I found that does all of this.
https://github.com/wcpro/ScaffR/tree/master/src/ScaffR.Security/content/CodeTemplates/Scaffolders/ScaffR.Security
You may have to do a little digging but its all there.
Here is the code for the http module
public class ClaimsTransformationHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PostAuthenticateRequest += context_PostAuthenticateRequest;
}
void context_PostAuthenticateRequest(object sender, EventArgs e)
{
var context = ((HttpApplication) sender).Context;
if (FederatedAuthentication.SessionAuthenticationModule != null &&
FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(context.Request.Cookies))
{
return;
}
var transformer = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager;
if (transformer != null)
{
var transformedPrincipal = transformer.Authenticate(context.Request.RawUrl, context.User as ClaimsPrincipal);
context.User = transformedPrincipal;
Thread.CurrentPrincipal = transformedPrincipal;
}
}
public void Dispose() { }
}
Here is the Claims Transformer
public partial class ClaimsTransformer : ClaimsAuthenticationManager
{
partial void SetCustomPrincipalClaims(IUserService userService, ref ClaimsPrincipal principal);
public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
{
if (!incomingPrincipal.Identity.IsAuthenticated)
{
return incomingPrincipal;
}
var newPrincipal = Transform(incomingPrincipal);
EstablishSession(newPrincipal);
return newPrincipal;
}
ClaimsPrincipal Transform(ClaimsPrincipal incomingPrincipal)
{
var nameClaim = incomingPrincipal.Identities.First().FindFirst(ClaimTypes.Name);
var userService = DependencyResolver.Current.GetService<IUserService>();
var user = userService.GetByUsername(nameClaim.Value);
var id = new ApplicationIdentity(user);
var principal = new ClaimsPrincipal(id);
SetCustomPrincipalClaims(userService, ref principal);
return principal;
}
private void EstablishSession(ClaimsPrincipal principal)
{
if (HttpContext.Current != null)
{
var sessionToken = new SessionSecurityToken(principal);
FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
}
}
}
Then here is the configuration
<?xml version="1.0" encoding="utf-8"?>
<system.identityModel>
<identityConfiguration>
<claimsAuthenticationManager type="Barbarella.Core.Common.Security.ClaimsTransformer, Barbarella.Core" />
</identityConfiguration>
</system.identityModel>
And this...
<system.identityModel.services>
<federationConfiguration>
<cookieHandler mode="Default" requireSsl="false" />
</federationConfiguration>
</system.identityModel.services>
And this...
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="ClaimsTransformationModule" type="Barbarella.Core.Common.Security.ClaimsTransformationHttpModule, Barbarella.Core" />
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</modules>
Dont forget to add your configuration sections
<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
Here is my code for the ApplicationIdentity (overrides ClaimsIDentity)... This is the code that answers your question really...
public sealed partial class ApplicationIdentity : ClaimsIdentity
{
partial void SetCustomIdentityClaims(User user);
private readonly User _user;
public ApplicationIdentity(User user) : base("Application")
{
_user = user;
AddClaim(new Claim(ClaimTypes.Name, user.Username));
AddClaim(new Claim(ApplicationClaimTypes.UserId, user.Id.ToString(CultureInfo.InvariantCulture)));
AddClaim(new Claim(ApplicationClaimTypes.FirstName, user.FirstName));
AddClaim(new Claim(ApplicationClaimTypes.LastName, user.LastName));
AddClaim(new Claim("Time", DateTime.Now.ToString()));
SetCustomIdentityClaims(_user);
}
public User User
{
get { return _user; }
}
public int UserId
{
get { return int.Parse(FindFirst(ApplicationClaimTypes.UserId).Value); }
}
public string Username
{
get { return FindFirst(ClaimTypes.Name).Value; }
}
}
I've been following Steven Sanderson's book called Pro ASP.NET MVC Framework, and I'm running into an exception:
Could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.TypeLoadException: Could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'
.
Line 19: public WindsorControllerFactory()
Line 20: {
Line 21: container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
Line 22:
Line 23: var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t;
Here's my WindsorControllerFactory code:
public class WindsorControllerFactory : DefaultControllerFactory
{
WindsorContainer container;
public WindsorControllerFactory()
{
container = new WindsorContainer(new XmlInterpreter(new ConfigResource("castle")));
var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes() where typeof(IController).IsAssignableFrom(t) select t;
foreach (Type t in controllerTypes)
container.AddComponentLifeStyle(t.FullName, t, LifestyleType.Transient);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return (IController)container.Resolve(controllerType);
}
}
My Global.asax.cs code:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory());
}
And the web.config values:
<configSections>
< section name="castle" type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor" />
</configSections>
<castle>
<components>
<component id="ProdsRepository" service="DomainModel.Abstract.IProductsRepository, DomainModel"
type="DomainModel.Concrete.SqlProductsRepository, DomainModel">
<parameters>
< connectionString>data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|SportsStore.mdf;User Instance=true< /connectionString>
</parameters>
</component>
</components>
</castle>
My question is why could not load type 'DomainModel.Abstract.IProductsRepository' from assembly 'DomainModel'. ?
A possible explanation for this error is that the IProductsRepository interface is not public and/or is not placed inside the DomainModel.Abstract namespace in the DomainModel assembly. Make sure that the definition looks like this and that it is part of the DomainModel project:
namespace DomainModel.Abstract
{
public interface IProductsRepository
{
...
}
}
The same stands true for the DomainModel.Concrete.SqlProductsRepository, DomainModel class that you've defined.