问题的标题在实际情况下可能有不同的含义。
历史简介:
我们有现有代码可以在 azure 表中执行 CRUD 操作。但它只能在同一个 Class 类型上使用 InserOrMergeBatch。我需要的是一种能够添加不同类型的类的方法,只要它们具有相同的基类。Partitionkey 应该不是问题,因为它是以其他方式处理的。
所以这就是问题所在。
- 创建一个可以为特定基类创建队列的类
- 创建的类必须能够添加任何类型的对象,只要它具有所需的基类
例如,我有这两个基类:人类和动物
public class Human
{
public int Height { get; set; }
public int Weight { get; set; }
}
public class Animal
{
public string Breed { get; set; }
public string Family { get; set; }
}
被其他一些类使用:
public class Eye : Human
{
public string Color { get; set; }
}
public class Nose : Human
{
public string Type { get; set; }
}
public class Teeth : Human
{
public int Count { get; set; }
}
public class Dog : Animal
{
public string NoseColor { get; set; }
}
public class Cat : Animal
{
public string EyeColor { get; set; }
}
第一个问题是创建一个具有一些必需方法的类:
public class AzureTableBatchCrud
{
public void CreateQueue( /* Specify the type of base class. */ )
{
}
public void AddQueue( /* Accept single object or list of objects of any type */ )
{
/* Must ensure that the added objects are inherited on same base class */
}
public bool ExecuteQueue()
{
/* Insert or merge objects on azure table */
return false;
}
}
为了更清楚,让我们使用这个类:
public class SampleUsage
{
public void SampleInsert()
{
// Example 1: Creating AzureTableBatchCrud with base class 'Human'
AzureTableBatchCrud sample1 = new AzureTableBatchCrud();
sample1.CreateQueue(Human);
// Right! because their base class is 'Human'
Eye eye1 = new Eye();
Nose nose1 = new Nose();
Teeth teeth1 = new Teeth();
sample1.AddQueue(eye1);
sample1.AddQueue(nose1);
sample1.AddQueue(teeth1);
// Wrong! because base class is not 'Human'
Dog dog1 = new Dog();
Cat cat1 = new Cat();
sample1.AddQueue(dog1); // must throw error
sample1.AddQueue(cat1); // must throw error
// Example 2: Creating AzureTableBatchCrud with base class 'Animal'
AzureTableBatchCrud sample2 = new AzureTableBatchCrud();
sample2.CreateQueue(Animal);
// Right! because base class is 'Animal'
Dog dog2 = new Dog();
Cat cat3 = new Cat();
sample2.AddQueue(dog2);
sample2.AddQueue(cat2);
// Wrong! because base class is not 'Animal'
Eye eye2 = new Eye();
Teeth teeth2 = new Teeth();
sample2.AddQueue(eye2); // must throw error
sample2.AddQueue(teeth2); // must throw error
}
}
希望这个例子能说明问题的概念。
我只知道 C# 中的基本编码,就此而言,这是一种非常先进的编码。我完全不知道。任何帮助,将不胜感激。
更新
我想我需要类的示例代码AzureTableBatchCrud
。
更新 2
我发布了这段代码,以便读者对这个问题有更多的了解。我还没有测试过这段代码,但我会在它工作后立即发布答案,以便未来可能遇到同样问题的读者可以参考。
namespace ProjectName.Domain.Entities
{
[DataContract]
public class NoSQLEntity: TableEntity
{
public NoSQLEntity()
{
}
public NoSQLEntity(string partitionKey, string rowKey)
{
PartitionKey = partitionKey;
RowKey = rowKey;
}
}
}
namespace ProjectName.Domain.Attribute
{
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false)]
public class AzureProjectionTable: System.Attribute
{
public string table;
}
}
namespace ProjectName.Data.DAOs
{
public class CrudBatch<T> where T : NoSQLEntity
{
private WomContext<T> _context;
CloudTable azuretable;
string table;
TableBatchOperation batchOperation;
List<T> itemlist;
public CrudBatch()
{
CloudStorageAccount storageAccount = ConfigWrapper.DataConnectionString();
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
var attrs = (Domain.Attribute.AzureProjectionTable[])
typeof(T).GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
table = attrs[0].table;
azuretable = tableClient.GetTableReference(table);
_context = new WomContext<T>(tableClient, table);
batchOperation = new TableBatchOperation();
itemlist = new List<T>();
}
public void AddQueue(object item)
{
var attrs = (Domain.Attribute.AzureProjectionTable[])
item.GetType().GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
{
if (table.Equals(attrs[0].table))
{
itemlist.Add((T)item);
}
}
}
public void AddQueue(List<object> item)
{
foreach (var i in item)
{
var attrs = (Domain.Attribute.AzureProjectionTable[])
i.GetType().GetCustomAttributes(typeof(Domain.Attribute.AzureProjectionTable), true);
if (attrs.Length > 0)
{
if (table.Equals(attrs[0].table))
{
itemlist.Add((T)i);
}
}
}
}
public bool ExecuteQueue(CrudAction action)
{
switch (action)
{
case CrudAction.InsertOrMergeBatch: return InsertOrMergeBatch();
case CrudAction.DeleteBatch: return DeleteBatch();
default: return false;
}
}
public void ClearQueue()
{
itemlist.Clear();
}
public T Get(string partitionKey, string rowKey)
{
TableOperation retrieve = TableOperation.Retrieve<T>(partitionKey, rowKey);
return (T)azuretable.Execute(retrieve).Result;
}
public IQueryable<T> Table()
{
return _context.Table;
}
private bool InsertOrMergeBatch()
{
foreach (var value in itemlist)
{
batchOperation.InsertOrMerge(value);
}
azuretable.ExecuteBatch(batchOperation).ToList();
return true;
}
private bool DeleteBatch()
{
TableBatchOperation batchOperation = new TableBatchOperation();
T deleteEntity;
foreach (var value in itemlist)
{
TableOperation retrieve = TableOperation.Retrieve<T>(value.PartitionKey, value.RowKey);
deleteEntity = (T)azuretable.Execute(retrieve).Result;
if (deleteEntity != null)
{
batchOperation.Delete(deleteEntity);
}
}
azuretable.ExecuteBatch(batchOperation);
return true;
}
}
public enum CrudAction
{
InsertOrMergeBatch,
DeleteBatch
}
}
namespace ProjectName.Data.Context
{
public class WomContext<T> : TableServiceContext where T: NoSQLEntity
{
private string table;
public WomContext(CloudTableClient client, string tablename)
: base(client)
{
table = tablename;
}
public TableServiceQuery<T> Table
{
get
{
return this.CreateQuery<T>(table).AsTableServiceQuery(this);
}
}
}
}
一个示例基类可以是:
namespace ProjectName.Domain.Entities.Carts
{
[Attribute.AzureProjectionTable(table = BaseTableNames.Cart)]
public class Cart: NoSQLEntity
{
public Cart() : base()
{
}
public Cart(string partitionkey, string rowkey)
: base(partitionkey, rowkey)
{
}
// Some properties...
}
}