LinqToSql dbml динамично переключает connectionstring

Тривиальный пример с Животным и Собакой: Вы зеркально отражаете vtable механизм C++ (в основном так или иначе). Вы также разделяете выделение и инстанцирование (Animal_Alloc, Animal_New), таким образом, мы не называем malloc () многократно. Мы должны также явно раздать this указатель.

, Если необходимо было сделать невиртуальные функции, это - trival. Вы просто не добавляете их к vtable и статическим функциям, не требуют this указатель. Множественное наследование обычно требует, чтобы несколько vtables разрешили неоднозначности.

кроме того, необходимо быть в состоянии использовать setjmp/longjmp, чтобы сделать обработку исключений.

struct Animal_Vtable{
    typedef void (*Walk_Fun)(struct Animal *a_This);
    typedef struct Animal * (*Dtor_Fun)(struct Animal *a_This);

    Walk_Fun Walk;
    Dtor_Fun Dtor;
};

struct Animal{
    Animal_Vtable vtable;

    char *Name;
};

struct Dog{
    Animal_Vtable vtable;

    char *Name; // Mirror member variables for easy access
    char *Type;
};

void Animal_Walk(struct Animal *a_This){
    printf("Animal (%s) walking\n", a_This->Name);
}

struct Animal* Animal_Dtor(struct Animal *a_This){
    printf("animal::dtor\n");
    return a_This;
}

Animal *Animal_Alloc(){
    return (Animal*)malloc(sizeof(Animal));
}

Animal *Animal_New(Animal *a_Animal){
    a_Animal->vtable.Walk = Animal_Walk;
    a_Animal->vtable.Dtor = Animal_Dtor;
    a_Animal->Name = "Anonymous";
    return a_Animal;
}

void Animal_Free(Animal *a_This){
    a_This->vtable.Dtor(a_This);

    free(a_This);
}

void Dog_Walk(struct Dog *a_This){
    printf("Dog walking %s (%s)\n", a_This->Type, a_This->Name);
}

Dog* Dog_Dtor(struct Dog *a_This){
    // Explicit call to parent destructor
    Animal_Dtor((Animal*)a_This);

    printf("dog::dtor\n");

    return a_This;
}

Dog *Dog_Alloc(){
    return (Dog*)malloc(sizeof(Dog));
}

Dog *Dog_New(Dog *a_Dog){
    // Explict call to parent constructor
    Animal_New((Animal*)a_Dog);

    a_Dog->Type = "Dog type";
    a_Dog->vtable.Walk = (Animal_Vtable::Walk_Fun) Dog_Walk;
    a_Dog->vtable.Dtor = (Animal_Vtable::Dtor_Fun) Dog_Dtor;

    return a_Dog;
}

int main(int argc, char **argv){
    /*
      Base class:

        Animal *a_Animal = Animal_New(Animal_Alloc());
    */
    Animal *a_Animal = (Animal*)Dog_New(Dog_Alloc());

    a_Animal->vtable.Walk(a_Animal);

    Animal_Free(a_Animal);
}

пз. Это тестируется на компиляторе C++, но должно быть легко заставить его работать над компилятором C.

6
задан Gert Arnold 24 August 2013 в 15:41
поделиться

1 ответ

Я бы использовал фабричный метод в частичном классе для DataContext. Имейте в виду, что строка подключения для DataContext отличается от обычной строки подключения ADO.NET.

Код .... Я никогда не использовал VB.NET, но это должно быть примерно так:

Partial Public Class MyDataContext

    ' GetConnectionString code here
    '

    Public Shared Function Create() As MyDataContext
        Return New MyDataContext(GetConnectionString())
    End Function
End Class

Используйте что вместо использования New MyDataContext () .

В качестве альтернативы вы можете вызывать

dc = New MyDataContext(GetConnectionString())

везде, где вы получаете новый экземпляр, но я предпочитаю фабричный метод.

Основная идея такая же, как и ваш подкласс, но без запутанного дополнительного имени класса. Частичные классы очень полезны, когда дело касается Entity Framework (или любых инструментов генерации кода). Вы можете добавить методы бизнес-логики в классы, созданные Entity Framework и т. Д.

9
ответ дан 10 December 2019 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: