0

问题的标题在实际情况下可能有不同的含义。
历史简介:

我们有现有代码可以在 azure 表中执行 CRUD 操作。但它只能在同一个 Class 类型上使用 InserOrMergeBatch。我需要的是一种能够添加不同类型的类的方法,只要它们具有相同的基类。Partitionkey 应该不是问题,因为它是以其他方式处理的。

所以这就是问题所在。

  1. 创建一个可以为特定基类创建队列的类
  2. 创建的类必须能够添加任何类型的对象,只要它具有所需的基类

例如,我有这两个基类:人类和动物

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...
    }
}
4

2 回答 2

0

You can get the base class as easy like this:

Type baseClass = childClassObject.GetType().BaseType;
于 2013-07-24T04:46:09.020 回答
0

如果我正确阅读了您的问题,那么您正在寻找一个Interface,而不是一个基类(尽管可能两者兼而有之)。

您的队列类将采用实现某些接口的对象

public class AzureTableBatchCrud
{
    public void AddQueue(IQueueableObject someItem)
    {
        /* Must ensure that the added objects are inherited on same base class */
    }

    public bool ExecuteQueue()
    {
        /* Insert or merge objects on azure table */
        return false;
    }
}

您需要定义该接口:

interface IQueueableObject
{
    void Queue();
}

我很难理解您的代码的目标。但我认为,如果你看一下接口是什么,你会发现你可以根据你的目的以一种有用的方式来组织事物。

于 2013-07-24T12:40:32.643 回答