Aracılığıyla paylaş


C++ Standart Kitaplığı Temelli Koleksiyon Uygulama

ATL, nesnelerinize C++ Standart Kitaplık tabanlı koleksiyon arabirimlerini hızlı bir şekilde uygulamanızı sağlayan arabirim sağlar ICollectionOnSTLImpl . Bu sınıfın nasıl çalıştığını anlamak için, Otomasyon istemcilerini hedefleyen salt okunur bir koleksiyon uygulamak için bu sınıfı kullanan basit bir örnek (aşağıda) üzerinden çalışacaksınız.

Örnek kod ATLCollections örneğinden alınıyor.

Bu yordamı tamamlamak için şunları yapacaksınız:

Yeni Basit Nesne Oluşturma

Uygulama Ayarları altındaki Öznitelikler kutusunun temizlendiğinden emin olarak yeni bir proje oluşturun. adlı Wordsbasit bir Nesne oluşturmak için ATL Sınıf Ekle iletişim kutusunu ve Basit Nesne Ekleme Sihirbazı'nı kullanın. adlı IWords bir çift arabirimin oluşturulduğundan emin olun. Oluşturulan sınıfın nesneleri, bir sözcük koleksiyonunu (yani dizeleri) temsil etmek için kullanılır.

IDL Dosyasını Düzenleme

Şimdi IDL dosyasını açın ve aşağıda gösterildiği gibi salt okunur koleksiyon arabirimine dönüştürmek IWords için gereken üç özelliği ekleyin:

[
   object,
   uuid(7B3AC376-509F-4068-87BA-03B73ADC359B),
   dual,                                                    // (1)
   nonextensible,                                           // (2)
   pointer_default(unique)
]
interface IWords : IDispatch
{
   [id(DISPID_NEWENUM), propget]                            // (3)
   HRESULT _NewEnum([out, retval] IUnknown** ppUnk);

   [id(DISPID_VALUE), propget]                              // (4)
   HRESULT Item([in] long Index, [out, retval] BSTR* pVal); // (5)

   [id(0x00000001), propget]                                // (6)
   HRESULT Count([out, retval] long* pVal);

};

Bu, Otomasyon istemcileri göz önünde bulundurularak tasarlanmış salt okunur koleksiyon arabirimi için standart formdur. Bu arabirim tanımındaki numaralandırılmış açıklamalar aşağıdaki açıklamalara karşılık gelir:

  1. Otomasyon istemcileri özelliğine aracılığıyla IDispatch::Invokeeriştiğinden _NewEnum koleksiyon arabirimleri genellikle çifttir. Ancak, Otomasyon istemcileri vtable aracılığıyla kalan yöntemlere erişebilir, bu nedenle çift arabirimler dispinterfaces için tercih edilir.

  2. Çift arabirim veya dispinterface çalışma zamanında genişletilmeyecekse (başka bir ifadeyle ek yöntemler veya özellikler IDispatch::Invokesağlamayacaksınız), tanımınıza genişletilebilir olmayan özniteliği uygulamanız gerekir. Bu öznitelik, Otomasyon istemcilerinin derleme zamanında tam kod doğrulaması gerçekleştirmesini sağlar. Bu durumda, arabirim genişletilmemelidir.

  3. Otomasyon istemcilerinin bu özelliği kullanabilmesini istiyorsanız doğru DISPID önemlidir. (DISPID_NEWENUM yalnızca bir alt çizgi olduğunu unutmayın.)

  4. Özelliğin DISPID Item değeri olarak herhangi bir değer sağlayabilirsiniz. Ancak, Item genellikle koleksiyonun varsayılan özelliği yapmak için DISPID_VALUE kullanır. Bu, Otomasyon istemcilerinin açıkça adlandırmadan özelliğine başvurmasını sağlar.

  5. özelliğinin dönüş değeri Item için kullanılan veri türü, COM istemcileri açısından koleksiyonda depolanan öğenin türüdür. Arabirim dizeleri döndürür, bu nedenle standart COM dize türü olan BSTR'yi kullanmanız gerekir. Kısa süre içinde göreceğiniz gibi verileri dahili olarak farklı bir biçimde depolayabilirsiniz.

  6. Özelliğin DISPID değeri Count için kullanılan değer tamamen rastgeledir. Bu özellik için standart DISPID yoktur.

Depolama ve Açığa Çıkarma için Tür Tanımları Oluşturma

Koleksiyon arabirimi tanımlandıktan sonra verilerin nasıl depolanacağına ve verilerin numaralandırıcı aracılığıyla nasıl gösterileceğine karar vermeniz gerekir.

Bu soruların yanıtları, yeni oluşturduğunuz sınıfınız için üst bilgi dosyasının üst kısmına ekleyebileceğiniz bir dizi tür tanımı biçiminde sağlanabilir:

// Store the data in a vector of std::strings
typedef std::vector< std::string >         ContainerType;

// The collection interface exposes the data as BSTRs
typedef BSTR                               CollectionExposedType;
typedef IWords                             CollectionInterface;

// Use IEnumVARIANT as the enumerator for VB compatibility
typedef VARIANT                            EnumeratorExposedType;
typedef IEnumVARIANT                       EnumeratorInterface;

Bu durumda, verileri std::strings öğesinin std::vektör olarak depolayacaksınız. std::vector , yönetilen bir dizi gibi davranan bir C++ Standart Kitaplık kapsayıcı sınıfıdır. std::string , C++ Standart Kitaplığı'nın dize sınıfıdır. Bu sınıflar, bir dize koleksiyonuyla çalışmayı kolaylaştırır.

Visual Basic desteği bu arabirimin başarısı için çok önemli olduğundan, özelliği tarafından döndürülen numaralandırıcı arabirimi _NewEnum desteklemelidir IEnumVARIANT . Bu, Visual Basic tarafından anlaşılan tek numaralandırıcı arabirimidir.

Kopyalama İlkesi Sınıfları için Tür Tanımları Oluşturma

Şimdiye kadar oluşturduğunuz tür tanımları, numaralandırıcı ve koleksiyon tarafından kullanılacak kopyalama sınıfları için daha fazla tür tanımı oluşturmak için ihtiyacınız olan tüm bilgileri sağlar:

// Typedef the copy classes using existing typedefs
typedef VCUE::GenericCopy<EnumeratorExposedType, ContainerType::value_type> EnumeratorCopyType;
typedef VCUE::GenericCopy<CollectionExposedType, ContainerType::value_type> CollectionCopyType;

Bu örnekte, ATLCollections örneğinden VCUE_Copy.h ve VCUE_CopyString.h içinde tanımlanan özel GenericCopy sınıfı kullanabilirsiniz. Bu sınıfı başka kodlarda kullanabilirsiniz, ancak kendi koleksiyonlarınızda kullanılan veri türlerini desteklemek için daha fazla uzmanlık GenericCopy tanımlamanız gerekebilir. Daha fazla bilgi için bkz . ATL Kopyalama İlkesi Sınıfları.

Numaralandırma ve Koleksiyon için Typedef oluşturma

Artık bu duruma yönelik ve ICollectionOnSTLImpl sınıflarını özelleştirmek CComEnumOnSTL için gereken tüm şablon parametreleri tür tanımları biçiminde sağlanmıştır. Özelleştirmelerin kullanımını basitleştirmek için aşağıda gösterildiği gibi iki tür tanımı daha oluşturun:

typedef CComEnumOnSTL< EnumeratorInterface, &__uuidof(EnumeratorInterface), EnumeratorExposedType, EnumeratorCopyType, ContainerType > EnumeratorType;
typedef ICollectionOnSTLImpl< CollectionInterface, ContainerType, CollectionExposedType, CollectionCopyType, EnumeratorType > CollectionType;

ŞimdiCollectionType, daha önce tanımlanan arabirimi uygulayan IWords ve destekleyen IEnumVARIANTbir numaralandırıcı sağlayan bir özelleştirmenin ICollectionOnSTLImpl eş anlamlısı.

Sihirbaz Tarafından Oluşturulan Kodu Düzenleme

Şimdi aşağıda gösterildiği gibi yerine typedef IWordsile temsil edilen arabirim uygulamasından CollectionType türetmelisinizCWords:

class ATL_NO_VTABLE CWords :
   public CComObjectRootEx<CComSingleThreadModel>,
   public CComCoClass<CWords, &CLSID_Words>,
   // 'CollectionType' replaces 'IWords' in next line
   public IDispatchImpl<CollectionType, &IID_IWords, &LIBID_NVC_ATL_COMLib, /*wMajor =*/ 1, /*wMinor =*/ 0>
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_WORDS)


BEGIN_COM_MAP(CWords)
   COM_INTERFACE_ENTRY(IWords)
   COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// Remainder of class declaration omitted.

Koleksiyonu Doldurmak için Kod Ekleme

Geriye kalan tek şey vektöre veri eklemektir. Bu basit örnekte, sınıfının oluşturucusunda koleksiyona birkaç sözcük ekleyebilirsiniz:

CWords()
{
    m_coll.push_back("this");
    m_coll.push_back("is");
    m_coll.push_back("a");
    m_coll.push_back("test");
}

Artık kodu istediğiniz istemciyle test edebilirsiniz.

Ayrıca bkz.

Koleksiyonlar ve Numaralandırıcılar
ATLCollections Örneği
ATL Kopyalama İlkesi Sınıfları