Çözüldü C# İki sınıf arasında Interface ile bağlantı oluştururken parametrelerin uyuşmaması

Bu konu çözüldü olarak işaretlenmiştir. Çözülmediğini düşünüyorsanız konuyu rapor edebilirsiniz.
Katılım
11 Eylül 2020
Mesajlar
1.857
Çözümler
6
Yer
Almanya
Daha fazla  
Cinsiyet
Erkek
Meslek
König
Merhaba. Interface lerle ilgili bir sorum var. Eğer iki sınıf birbiriyle aynı metotlara sahipse, aynı işleri yapıyorsa ve aynı interface den miras alıyorsa, ama farklı parametrelere ihtiyaç duyuyorsa bunun hakkında ne yapabiliriz? Aşağıda bir örneğini verdim. Oracle sınıfı ve MSSQL sınıfı aynı işi yapıyor ama aralarında sadece tek bir fark var, biri OracleCommand, biri SQLCommand nesnesine ihtiyaç duyuyor.
C#:
class MetotlariCagiracagimizClass
{
    public void RunProcedure(IDataBase IDB)
    {
        IDB.RunProcedure(//VerilenParametreler//)
    }
}

class MSSQL : IDataBase
{
 public void RunStoredProcedure(ref SqlCommand cmd, string SPName, string[] ParameterNames, object[] Values)
 {
   //MSSQL sınıfı normal çalışıyor.
 }
}
class OracleSQL : IDataBase
{
  public void RunStoredProcedure(ref SqlCommand cmd, string SPName, string[] ParameterNames, object[] Values)
  {
    //Burada Oracle serveri, mesela SQLCommand yerine OracleCommand diye bir sınıfa ihtiyaç duyuyor olsun. Ama biz ona SQLCommand vermek zorunda kaldık.
  }
}
interface IDataBase
{
   void RunProcedure(ref SqlCommand cmd, string SPName, string[] ParameterNames, object[] Values);
}
 
Çözüm
Strategy patternine ihtiyacınız var, ben öyle anladım.

Kısaca yapısı şöyle (Java syntaxı ile anlatmaya çalışıyorum ama siz anlarsınız, kodu da pseudocode olarak yazıyorum o yüzden code tagleri kullanmadım)

Dbstrategy diye bir interface, içinde executeQuery diye tek bir method

public interface dbstrategy
{
Public Void executeQuery();
}


Bu interface i implemente eden birkaç tane alt sınıf olsun, implemente eden sınıflar executeQuery methodunu override ederler, bunların constructorları da farklı parametreler alırlar. Örneğin şöyle;

public class sqlstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public sqlstrategy(sqlcommand, parameternames, hostIp, username, password vb. vb. Gibi )
{//Bla bla
}

@Override
Public Void executeQuery()
{
//Sql ile execute işlemi
}

}


Mesela MongoDB için şöyle bir fark olur,

public class mongodbstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public mongodbstrategy(mongoquery, connectionString, queryMaxTimeout vb. vb.)
{
//Bla bla
}

@Override
Public Void executeQuery()
{
//Mongodb ile execute işlemi
}

}


dB işlemini execute edecek olan sınıfın adını executor koyalım; bu sınıf içinde bu işlem için bizi ilgilendiren methodun adı da execute olsun;

public class executor
{
//Başka methodlar, getterlar setterlar vb.

Public Void execute(dbStrategy strategy)
{

Strategy.executeQuery();
}
}


Execute işlemi, sizin ona yollayacağınız dbstrategy sınıfının executeQuery methodunu çalıştıran bir tür controllerdır.

Şimdi bu kod nasıl çalışır? Ben proje içinde a işlemi için SQL kullanacağım, b işlemi için MongoDB kullanacağım diyelim, şöyle istek atarım:

A işlemi
executor. Execute(New sqlstrategy(sqlcommand, parameternames, "10.0.0.1", "admin", "sqlpasswordum". Vb.))

-Verdiğim parametreler ile yeni bir sqlstrategy nesnesi (dbStrategy interfacei) oluşur.
-Executor sınıfının execute işlemine parametre olarak bu dbStrategy nesnesi gider
-Queryyi execute etme sorumluluğu kime ait? Strategy nesnesine ait. Ben ne tür bir strategy nesnesi gönderdim parametre olarak? SQL tipinde bir strategy nesnesi gönderdim. Gönderdiğim strategy nesnesi ne ise execute işlemini o yapar yani sqlcommand objesini alır, SQL dbsine bağlanır ve executeQuery methodu çalışır.

B işlemi
executor. Execute(New mongodbstrategy(mongoquery, "MongoDB://localhost: 27017", "1000". Vb.))
-Bu sefer mongodbstrategy diye bir dbstrategy interfacei oluşturuldu.
-Execute işlemini yapacak olan sınıf mondodbstrategy sınıfıdır. Gönderdiğim bilgiler ve query parametrelerine göre bağlanır ve execute işlemini yapar.

Benim bildiğim aynı işlemi farklı parametreler ile yapan clean code a uygun kod böyle yazılır, farklı DB'lerde çalışma durumu için size böyle bir örnek verdim, aslında farklı dosya sistemleri ile çalışması istenen, farklı OS üzerinde çalışılacak ve farklı settinglere sahip olması istenen, ya da farklı encoding (mesela eski bir sistemde ASCII iken TR Windows bir sistemde CP1254 kullanacak) işlemleri gereken vb. durumlarda kullandığımız bir patterndir. Sizin sorununuzu doğru anladıysam ve sizin işinizi görecek şey bu verdiğim örnektekine benzer bir şeylerse strategy design patternini araştırabilirsiniz.
SQLCommand olanları değer içinde göndermeyin. Sonradan ekletin. Bu sayede ister OracleCommand veya SQLCommand arasında geçişi küçük bir denetleme ile yapabilirsiniz.

Interface yapısı için bu şekilde değer vermek doğru değil.

Ben olsam Constructor olarak yapardım.
 
Interface yapısı için bu şekilde değer vermek doğru değil.
Peki nasıl değerler vermeliyim? Mesela şu tarz mı olmalı?
C#:
class MetotlariCalistiracagimClass
{
  public void RunProcedure(IDataBase IDB)
  {
      IDB.RunProcedure(IDB);
  }
}
interface IDB
{
    void RunProcedure(IDataBase IDB);
}

SQLCommand olanları değer içinde göndermeyin. Sonradan ekletin. Bu sayede ister OracleCommand veya SQLCommand arasında geçişi küçük bir denetleme ile yapabilirsiniz.
Yani Metotları çalıştıracağım class ta, Eğer IDB nin tipi MSSQL ise SQLCommand, Eğer OracleSQL ise OracleCommand ı mı parametre olarak vermeliyim? Bu temiz kod yazmaya ters düşebilecek birşey değil mi?
 
@II.Wilhelm temiz koda ters düşecek bir durum yok burada. Farklı veri tabanı motorlarına erişmek için bazen böyle yapmak gerekiyor. Bir proje genelde tek bir veri tabanı motoru ile kontrol edilir. O yüzden sizin yapınıza göre sıkıntı olmaz.

Ancak üstte dediğim gibi, Kalıtım ve Polimorfizm kullanırsanız sorun olmaz.
 
Bahsettiğim şey aslen bir proxy class, design pattern içinde yeri olan bir konu. Yazdığın sınıf farklı library sınıflarından yararlanacaksa bu tarz şeyler kullanmak gerekebiliyor. Ya da oturup kendin ortak bir command sınıfı yazacaksın, benzer objeler ise Cast'de edilebilir tabii... Birçok seçenek var.
 
Strategy patternine ihtiyacınız var, ben öyle anladım.

Kısaca yapısı şöyle (Java syntaxı ile anlatmaya çalışıyorum ama siz anlarsınız, kodu da pseudocode olarak yazıyorum o yüzden code tagleri kullanmadım)

Dbstrategy diye bir interface, içinde executeQuery diye tek bir method

public interface dbstrategy
{
Public Void executeQuery();
}


Bu interface i implemente eden birkaç tane alt sınıf olsun, implemente eden sınıflar executeQuery methodunu override ederler, bunların constructorları da farklı parametreler alırlar. Örneğin şöyle;

public class sqlstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public sqlstrategy(sqlcommand, parameternames, hostIp, username, password vb. vb. Gibi )
{//Bla bla
}

@Override
Public Void executeQuery()
{
//Sql ile execute işlemi
}

}


Mesela MongoDB için şöyle bir fark olur,

public class mongodbstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public mongodbstrategy(mongoquery, connectionString, queryMaxTimeout vb. vb.)
{
//Bla bla
}

@Override
Public Void executeQuery()
{
//Mongodb ile execute işlemi
}

}


dB işlemini execute edecek olan sınıfın adını executor koyalım; bu sınıf içinde bu işlem için bizi ilgilendiren methodun adı da execute olsun;

public class executor
{
//Başka methodlar, getterlar setterlar vb.

Public Void execute(dbStrategy strategy)
{

Strategy.executeQuery();
}
}


Execute işlemi, sizin ona yollayacağınız dbstrategy sınıfının executeQuery methodunu çalıştıran bir tür controllerdır.

Şimdi bu kod nasıl çalışır? Ben proje içinde a işlemi için SQL kullanacağım, b işlemi için MongoDB kullanacağım diyelim, şöyle istek atarım:

A işlemi
executor. Execute(New sqlstrategy(sqlcommand, parameternames, "10.0.0.1", "admin", "sqlpasswordum". Vb.))

-Verdiğim parametreler ile yeni bir sqlstrategy nesnesi (dbStrategy interfacei) oluşur.
-Executor sınıfının execute işlemine parametre olarak bu dbStrategy nesnesi gider
-Queryyi execute etme sorumluluğu kime ait? Strategy nesnesine ait. Ben ne tür bir strategy nesnesi gönderdim parametre olarak? SQL tipinde bir strategy nesnesi gönderdim. Gönderdiğim strategy nesnesi ne ise execute işlemini o yapar yani sqlcommand objesini alır, SQL dbsine bağlanır ve executeQuery methodu çalışır.

B işlemi
executor. Execute(New mongodbstrategy(mongoquery, "MongoDB://localhost: 27017", "1000". Vb.))
-Bu sefer mongodbstrategy diye bir dbstrategy interfacei oluşturuldu.
-Execute işlemini yapacak olan sınıf mondodbstrategy sınıfıdır. Gönderdiğim bilgiler ve query parametrelerine göre bağlanır ve execute işlemini yapar.

Benim bildiğim aynı işlemi farklı parametreler ile yapan clean code a uygun kod böyle yazılır, farklı DB'lerde çalışma durumu için size böyle bir örnek verdim, aslında farklı dosya sistemleri ile çalışması istenen, farklı OS üzerinde çalışılacak ve farklı settinglere sahip olması istenen, ya da farklı encoding (mesela eski bir sistemde ASCII iken TR Windows bir sistemde CP1254 kullanacak) işlemleri gereken vb. durumlarda kullandığımız bir patterndir. Sizin sorununuzu doğru anladıysam ve sizin işinizi görecek şey bu verdiğim örnektekine benzer bir şeylerse strategy design patternini araştırabilirsiniz.
 
Son düzenleme:
Çözüm
Strategy patternine ihtiyacınız var, ben öyle anladım.

Kısaca yapısı şöyle (Java syntaxı ile anlatmaya çalışıyorum ama siz anlarsınız, kodu da pseudocode olarak yazıyorum o yüzden code tagleri kullanmadım)

Dbstrategy diye bir interface, içinde executeQuery diye tek bir method

public interface dbstrategy
{
Public Void executeQuery();
}


Bu interface i implemente eden birkaç tane alt sınıf olsun, implemente eden sınıflar executeQuery methodunu override ederler, bunların constructorları da farklı parametreler alırlar. Örneğin şöyle;

public class sqlstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public sqlstrategy(sqlcommand, parameternames, hostIp, username, password vb. vb. Gibi )
{//Bla bla
}

@Override
Public Void executeQuery()
{
//Sql ile execute işlemi
}

}


Mesela MongoDB için şöyle bir fark olur,

public class mongodbstrategy implements dbstrategy
{
//Getter setter vb.

//Constructor
Public mongodbstrategy(mongoquery, connectionString, queryMaxTimeout vb. vb.)
{
//Bla bla
}

@Override
Public Void executeQuery()
{
//Mongodb ile execute işlemi
}

}


dB işlemini execute edecek olan sınıfın adını executor koyalım; bu sınıf içinde bu işlem için bizi ilgilendiren methodun adı da execute olsun;

public class executor
{
//Başka methodlar, getterlar setterlar vb.

Public Void execute(dbStrategy strategy)
{

Strategy.executeQuery();
}
}


Execute işlemi, sizin ona yollayacağınız dbstrategy sınıfının executeQuery methodunu çalıştıran bir tür controllerdır.

Şimdi bu kod nasıl çalışır? Ben proje içinde a işlemi için SQL kullanacağım, b işlemi için MongoDB kullanacağım diyelim, şöyle istek atarım:

A işlemi
executor. Execute(New sqlstrategy(sqlcommand, parameternames, "10.0.0.1", "admin", "sqlpasswordum". Vb.))

-Verdiğim parametreler ile yeni bir sqlstrategy nesnesi (dbStrategy interfacei) oluşur.
-Executor sınıfının execute işlemine parametre olarak bu dbStrategy nesnesi gider
-Queryyi execute etme sorumluluğu kime ait? Strategy nesnesine ait. Ben ne tür bir strategy nesnesi gönderdim parametre olarak? SQL tipinde bir strategy nesnesi gönderdim. Gönderdiğim strategy nesnesi ne ise execute işlemini o yapar yani sqlcommand objesini alır, SQL dbsine bağlanır ve executeQuery methodu çalışır.

B işlemi
executor. Execute(New mongodbstrategy(mongoquery, "MongoDB://localhost: 27017", "1000". Vb.))
-Bu sefer mongodbstrategy diye bir dbstrategy interfacei oluşturuldu.
-Execute işlemini yapacak olan sınıf mondodbstrategy sınıfıdır. Gönderdiğim bilgiler ve query parametrelerine göre bağlanır ve execute işlemini yapar.

Benim bildiğim aynı işlemi farklı parametreler ile yapan clean code a uygun kod böyle yazılır, farklı DB'lerde çalışma durumu için size böyle bir örnek verdim, aslında farklı dosya sistemleri ile çalışması istenen, farklı OS üzerinde çalışılacak ve farklı settinglere sahip olması istenen, ya da farklı encoding (mesela eski bir sistemde ASCII iken TR Windows bir sistemde CP1254 kullanacak) işlemleri gereken vb. durumlarda kullandığımız bir patterndir. Sizin sorununuzu doğru anladıysam ve sizin işinizi görecek şey bu verdiğim örnektekine benzer bir şeylerse strategy design patternini araştırabilirsiniz.
Teşekkür ederim hocam. Oldukça anlaşılır olmuş, kafama daha iyi oturdu. Daha Solid prensiplerine yeni başladım, design pattern ları ise henüz bilmiyorum. Yakında bunları daha detaylı bir şekilde öğreneceğim.
 

Technopat Haberler

Yeni konular

Geri
Yukarı