问题
CustomerService is a webservice and it is getting called successfully but I am unable to access SelectCommand in the Any method. I think I am missing something here, could anyone suggest.
public class CustomerService : Service
{
private readonly IDbConnection _dbConnection; // injected successfully
public ServiceCommand SelectCommand {get;set;}
public CustomerService(IDBConnection dbConnection)
{
_dbConnection = dbConnection;
}
public Customer Any(CustomerRequest request)
{
//_dbconnection is available
//but selectcommand is null here
//db operations
}
}
[Route("/customers")]
public class CustomerRequest
{
public string name { get; set; }
}
public class ServiceCommand
{
public string SQL { get; set; }
public CommandType CommandType { get; set; }
public ServiceCommand()
{
CommandType = CommandType.Text;
}
}
I've initialized the connection by inheriting AppHostBase
public override void Configure(Container container) {
container.Register<IDbConnectionFactory>(
c => new OrmLiteConnectionFactory(ConfigurationManager.ConnectionStrings["default"].ConnectionString,
SqlServerDialect.Provider));
container.Register<IDbConnection>(c => c.Resolve<IDbConnectionFactory>().OpenDbConnection()).ReusedWithin(ReuseScope.Request);
}
When I tried to write unit test by setting SelectCommand explicitly, it works. But I am unable to test how it works by not setting the value, I assumed it takes the default value set in the constructor.
var service = new CustomerService(InMemoryTestDatabase.OpenDbConnection());
service.SelectCommand = new ServiceCommand() { SQL = "SELECT * FROM customers" };
Edit
IDbConnection in the constructor is working fine but my problem is with SelectCommand which is a public property here. My intention is, if the webservice is called normally I'd hit the actual database by setting query like below in the constructor.
SelectCommand = new ServiceCommand() {Text = "sp_getcustomers"};
But when I test it, I would set it to sqllite database and change my query to table "select * from customers" since sqllite doesn't support sp's. As mentioned unit tests are working fine, but the service is not able to initialize the public properties.
If I initialize a private readonly property same as _dbConnection like below, it works fine but I would like to inject command for the service explicitly.
private readonly IDbConnection _dbConnection;
private readonly ServiceCommand _selectCommand;
public CustomerService(IDBConnection dbConnection)
{
__dbConnection = dbConnection;
_selectCommand = new ServiceCommand(){Text = "sp_getCustomers"};
}
回答1:
Be sure to include all relevant info and context about your question as this would be impossible to infer without out-of-hand knowledge on how you're using it. E.g. what does your IOC look like?
You're asking for an IDbConnection
in your constructor:
public CustomerService(IDBConnection dbConnection)
{
SelectCommand = new ServiceCommand();
}
But it's very likely you're only registering an IDbConnectionFactory
, so there doesn't exist any registered dependency with IDbConnection
.
If you inheriting from Service class you've already got the IDbConnectionFactory
injected and access to the IDbConnection
with the base.Db property:
private IDbConnection db;
public virtual IDbConnection Db
{
get { return db ?? (db = TryResolve<IDbConnectionFactory>().Open()); }
}
All public properties get injected by the IOC
The reason why SelectCommand property is null is because it's a public property. All of your Services public properties are attempted to be resolved by your Registered dependencies and because you don't have any registered dependencies of type ServiceCommand
it is overrided with null. If this was defined in your constructor instead it would've thrown a run-time exception, because it's just a property it's initialized to null.
If you change the visibility of SelectCommand
to protected, private, internal or static it wont be attempted to be injected by the IOC.
来源:https://stackoverflow.com/questions/15745074/how-to-assign-default-value-to-a-property