C#在运行时强制转换具体类变量(依赖项注入)
我正在尝试在我的项目中实现依赖项注入,以连接SQL server进行单元测试。 我使用了SQL库中内置的抽象类,并为SqlCommand、SqlConnection和SqlTransaction创建了自己的模拟类。 下面是我的课程 我无法在编译时使用program.cs文件中名为AddWithValue的SqlCommand属性(SqlParameterCollection)方法 我在犯错误 “DbParameterCollection”不包含“AddWithValue”的定义,并且找不到接受“DbParameterCollection”类型的第一个参数的可访问扩展方法“AddWithValue”(是否缺少using指令或程序集引用? 对象DbParameterCollection驻留在抽象类DbCommand中,但是具有AddWithValue方法的给定对象驻留在具体类SqlCommand中 我如何告诉编译器应该对类SqlCommand的属性而不是DBCommand调用AddWithValue方法 这是我所有的课 由于我是新手,我还没有发现任何在运行时使用反射注入具体类的方法,或者可能有其他方法 SQLWrapper.csC#在运行时强制转换具体类变量(依赖项注入),c#,sql-server,C#,Sql Server,我正在尝试在我的项目中实现依赖项注入,以连接SQL server进行单元测试。 我使用了SQL库中内置的抽象类,并为SqlCommand、SqlConnection和SqlTransaction创建了自己的模拟类。 下面是我的课程 我无法在编译时使用program.cs文件中名为AddWithValue的SqlCommand属性(SqlParameterCollection)方法 我在犯错误 “DbParameterCollection”不包含“AddWithValue”的定义,并且找不到接受“
namespace DAL
{
public class SQLWrapper
{
private Context _ctx;
private string _referenceID;
private string _connectionKey;
private static string _connectionString;
private int _timeout = 180;
public SQLWrapper(Context ctx, string referenceID, string connectionKey)
{
_ctx = ctx;
_referenceID = referenceID;
_connectionKey = connectionKey;
}
public async Task<Error> GetConnectingStringAsync()
{
// Gets the connection string from config
}
/// <summary>
/// Executes the statement.
/// </summary>
/// <param name="ctx"></param>
/// <param name="command"></param>
/// <returns></returns>
public async Task<Error> ExecuteStatementAsync()
{
Error error = null;
try
{
error = await GetConnectingStringAsync();
if (error != null)
{
return error;
}
using (_ctx.connection)
{
_ctx.connection.ConnectionString = _connectionString;
_ctx.command.CommandTimeout = _timeout;
try
{
await _ctx.connection.OpenAsync();
_ctx.command.Connection = _ctx.connection;
_ctx.command.Prepare();
_ctx.transaction = _ctx.connection.BeginTransaction();
await _ctx.command.ExecuteNonQueryAsync();
_ctx.transaction.Commit();
return null;
}
catch (Exception ex)
{
if (_ctx.transaction != null)
{
_ctx.transaction.Rollback();
}
return error;
}
}
}
catch (Exception ex)
{
return error;
}
}
}
}
MockSQL.cs
namespace DAL
{
class MockSQL : DbConnection
{
private string _connectionString;
public override string ConnectionString { get => ""; set => _connectionString = value; }
public override string Database => throw new NotImplementedException();
public override string DataSource => throw new NotImplementedException();
public override string ServerVersion => throw new NotImplementedException();
public override ConnectionState State => throw new NotImplementedException();
public override void ChangeDatabase(string databaseName)
{
throw new NotImplementedException();
}
public override void Close()
{
throw new NotImplementedException();
}
public override void Open()
{
return;
}
protected override DbTransaction BeginDbTransaction(IsolationLevel isolationLevel)
{
return new MockTransaction();
}
protected override DbCommand CreateDbCommand()
{
throw new NotImplementedException();
}
}
}
MockTransaction.cs
namespace DAL
{
class MockTransaction : DbTransaction
{
public override IsolationLevel IsolationLevel => throw new NotImplementedException();
protected override DbConnection DbConnection => throw new NotImplementedException();
public override void Commit()
{
return;
}
public override void Rollback()
{
throw new NotImplementedException();
}
}
}
Context.cs
public class Context
{
public DbConnection connection;
public DbCommand command;
public DbTransaction transaction;
public ICongigRPC config;
}
ContextInitializer.cs
public static class ContextInitializer
{
public static Context InitCtx()
{
return new Context()
{
connection = new SqlConnection(),
command = new SqlCommand(),
transaction = null
};
}
}
Program.cs
Context ctx = MockContextInitializer.MockInitCtx();
ctx.command.CommandText = "SELECT * FROM MEMBERMAPPING WHERE OldMemberID = @OldMemberID;";
ctx.command.Parameters.AddWithValue("@OldMemberID", "1234");
SQLWrapper wrapper = new SQLWrapper(ctx, "123", "123");
wrapper.ExecuteStatementAsync();
通过铸造???这不是代码审查,而是。。。这些课程有什么目的?无论如何,正如错误所述,声明为
DbParameterCollection
的成员没有AddWithValue()
方法,您无论如何都不应该使用该方法。它也不适用于非模拟类。只需使用Add(new XxxParameter(…)
。与其尝试创建框架提供的SQL工具的模拟,不如创建一个数据访问层来包装这些工具并实现更通用的、特定于上下文的接口。我隐约记得“AddWithValue”有点不推荐使用。为什么不“简单”:var parameter=command.CreateParameter();parameter.ParameterName=“@Key”;parameter.Value=“无论如何”;command.Parameters.Add(参数)
?@CodeCaster我正在为单元测试创建这些类,在这里我可以为我的业务逻辑返回样例模拟响应。我从互联网上了解到,我们可以使用依赖注入来实现单元测试,因此我尝试在不使用任何第三方软件包进行单元测试的情况下遵循这一点。
Context ctx = MockContextInitializer.MockInitCtx();
ctx.command.CommandText = "SELECT * FROM MEMBERMAPPING WHERE OldMemberID = @OldMemberID;";
ctx.command.Parameters.AddWithValue("@OldMemberID", "1234");
SQLWrapper wrapper = new SQLWrapper(ctx, "123", "123");
wrapper.ExecuteStatementAsync();