2014-01-28 4 views
1

은 가정하자 나는 다음 WCF 코드를 한 :매개 변수로 여러 메서드 (매개 변수 사용)를 전달하려면 어떻게해야합니까?

try 
    { 
     ServiceClient proxy = new ServiceClient(); 
     proxy.ClientCredentials.UserName.UserName = "user"; 
     proxy.ClientCredentials.UserName.Password = "password"; 
     proxy.GetData(2); 
     if (proxy.State = CommunicationState.Opened) 
     { 
      proxy.GetData("data"); 
     } 
     proxy.Close(); 
    } 
    catch (FaultException ex) 
    { 
     // handle the exception  
    } 

그리고 나는 시도 ... 캐치와 다른 논리가 반복적 것을 알 때문에, WCF 호출을 설정하는 것은 비싼 언급하지, 내가 보내려 이 기능에 대한 많은 "방법 및 매개 변수".

본질적으로 GetData(2)GetData("data")을 메소드 배열로 전달하고 비동기식 또는 동 기적으로 결과를 반환합니다.

어떻게하면됩니까?

결과 []와 결과 []에 대한 처리를 처리 할 두 개의 'ref'개체가 있다고 가정합니다. 그러나 "매개 변수가있는 메서드"를 다른 함수의 매개 변수로 전달하는 방법을 잘 모르겠습니다.

아마도이 다른 방법은 다른 매개 변수를 사용하여 동일한 함수에 대한 함수 포인터의 배열 일 수 있습니다.

누구든지이 일을 올바르게 수행 할 수 있습니까?

더 많은 정보는 :

나는이 질문 so I can optimize this approach to handling WCF exceptions and retries을 요구하고 있지만, 그래서 나는 항상 열려/각 호출 후 클라이언트를 종료 할 필요가 없습니다.

답변

7

사용 위임을하여 목록으로 전달합니다.

반환 값이 필요할 때 C# Func<T> 대리자가 사용됩니다.

List<Func<Data>> funcList = new List<Func<Data>>(); 
funcList.Add(() => GetData(2)); 

// You can use any condition as you otherwise would to add to the list. 
if (proxy.State = CommunicationState.Opened) 
{ 
    funcList.Add(() => GetData("data")); 
} 

List<Data> ProcessFuncs(List<Func<Data>> funcDatas) 
{ 
    List<Data> returnList = new List<Data>(); 
    foreach(var func in funcDatas) 
    { 
     returnList.Add(func()); 
    } 
} 

이것은 물론 단지 예이다 (리턴 종류가 동일한 것이면,이 작동 됨); 메서드에서 아무 것도 반환하지 않으면 C# Action 대리자를 사용할 수 있습니다.이 대리자는 작업을 실행하기 만하며 값을 반환하지 않습니다.

일부 의견에 응답
List<Action> actionList = new List<Action>(); 
actionList.Add(() => ProcessData("data")); // ProcessData is a void with no return type 
actionList.Add(() => ProcessData(2)); 

public void ProcessActions(List<Action> actions) 
{ 
    foreach(var action in actions) 
    { 
     action(); 
    } 
} 

:

class Program 
{ 
    public static string GetData(string item) { return item; } 
    public static string GetData(int item) { return item.ToString(); } 

    static void Main(string[] args) 
    { 
     string someLocalVar = "what is it?"; 
     int someLocalValueType = 3; 

     Func<string> test =() => 
     { 
      return GetData(someLocalVar); 
     }; 

     Func<string> test2 =() => GetData(someLocalValueType); 
     someLocalValueType = 5; 

     List<Func<string>> testList = new List<Func<string>>(); 

     testList.Add(() => GetData(someLocalVar)); 
     testList.Add(() => GetData(2)); 
     testList.Add(test); 
     testList.Add(test2); 

     someLocalVar = "something else"; 

     foreach(var func in testList) 
     { 
      Console.WriteLine(func()); 
     } 

     Console.ReadKey(); 
    } 
} 

결과는 다음과 같습니다 :

enter image description here

+0

무언가를 반환하는 경우에도 Action 버전을 사용할 수 있습니다. 과제를 람다에 포함시킬 수 있습니다. 그것은 위험 할 수 있지만 때로는 그것이 당신이 원하는 것일 수도 있습니다. – Magus

+0

예, 또는 람다 대신 액션에 대한 {} 본문을 가지고 무엇이든 할 수 있으며 액션에서 아무 것도 반환하지 않습니다. 많은 가능성. –

+0

코드가 컴파일되지 않는다고 생각하기 때문에 뭔가 빠졌습니다 ... "Delegate 'System.Func '에 인수가 하나도 없습니다." 메서드 호출과 같이 전달되는 인수를 사용하여 목록에 대리자를 추가 할 수는 없다고 확신합니다. – evanmcdonnal

0

당신은 C#을 위임을 사용할 수

대리자는 특정 매개 변수 목록과 방법에 대한 참조를 나타내며 유형을 반환 유형입니다. 대리자를 인스턴스화하면 해당 인스턴스를 호환 서명 및 반환 형식의 모든 메서드와 연결할 수 있습니다. 위임 인스턴스를 통해 메서드를 호출하거나 호출 할 수 있습니다. 대리자는 다른 메서드에 인수로 메서드를 전달하는 데 사용됩니다. 이벤트 처리기는 대리자를 통해 호출되는 메서드보다 더 많습니다 ( ). 사용자 지정 메서드를 만들고 특정 이벤트가 발생할 때 Windows 컨트롤과 같은 클래스에서 메서드 을 호출 할 수 있습니다. 이에

더 많은 : 다음 예는 대리인에게 선언 보여줍니다 http://msdn.microsoft.com/en-us/library/ms173171.aspx

1

우는 방법의 예입니다

이 코드는 컴파일은 모두 동일합니다 델리게이트와 그것들의 인자들을 모아서 t를 호출한다. 나중에 메서드 정의를 알지 못하게 내가 아는 한 하나의 일반 호출에서 다른 정의가있는 메소드를 호출하려면 이처럼 뭔가를해야한다.

List<Tuple<delegate, object[]>> delegates = new List<Tuple<delegate, object[]>>(); 

    delegates.Add(new Tuple<delegate, object[]>(new Func<Arg1Type, Arg2Type, ReturnType>(MyFunctionName), new object[] { arg1, arg2 }); 

    foreach (Tuple<delegate, object[]> d in delegates) 
    { 
     d.Item1.DynamicInvoke(d.Item2); 
    } 
하여 매개 변수에이 방식의 기능을 전달할 수
+0

나는'Action' 콜렉션을 가지고 람다에서 인수와 함수를 전달하는 것을 선호한다고 생각합니다. 청소기가 될 수도 있습니다. – Magus

+0

@Magus 내 코드가 조금 엉성한데, 반환 형식이 있기 때문에 Func 일 필요가 있습니다. 어디에도 지정하지 않고 있습니다.람다에서 args를 전달하는 코드에 대해서는 알지 못한다. 컴파일 할 수 없다는 것을 알 수있다. 사실, 100 % 컴파일되지 않습니다. 'List >'a와 b는 args이고 c는 리턴 타입이다. 그는 리턴 타입이 'Data' 인 함수를 선언하고, 임의의 args를 전달하려고합니다. 그들이 말하려하지 않는다고 말하면 ... 당신은 객체 배열과'DynamicInvoke'를 사용하여 이런 종류의 행동을 취해야합니다. – evanmcdonnal

+0

나는 문자열'b '의 줄을 따라 의미를 가졌다. 액션 a =() => b = SomeFunction (param1, param2);'b는 아마도 필드 여야합니다. 그것은 꽤 깨끗하고 똑같은 일을합니다. – Magus

0

:

public void strategy<R, T1, T2>(Func<R, T1, T2> f); 

public bool predicate(string a, string b); 

strategy<bool, string, string>(predicate); 

첫번째 라인 함수 f 접수 기능 strategy()를 선언하는 단계; 해당 함수는 R 유형을 반환하고 T1T2 유형의 두 매개 변수를 사용합니다.

두 번째 줄은 bool을 반환하고 두 개는 string을 허용하는 함수를 정의합니다.

세 번째 줄은 매개 변수로 조건자를 전달하는 전략을 호출합니다.

0

당신이 달성하려고하는지 이해할 수 있지만, 기본적으로 서비스가 GetData(int) 방법 및 GetData(string) 방법뿐만 아니라 비동기 프록시를 노출하는 경우, 당신은 같은 두 비동기 적으로 사용하여 뭔가를 호출해야 확실하지 :

var getData = proxy.GetDataAsync(2); 
var getData2 = proxy.GetDataAsync("data"); 

await Task.WhenAll(getData, getData2); 

// Gets the result using getData.Result...etc. 
1

위임자는 여기에서 사용하지 않을 것입니다. 왜냐하면 유형에 제약을 받고 끔찍하고 지나치게 복잡해지기 때문에 위임자를 사용하지 않을 것입니다. 한 번 설정되면 ServiceClient에 대한 자유로운 통치를 제공하는 콜백 만 있습니다. 나는 이것이 이름을 가진 패턴이라고 생각하지만 나는 모른다.

interface IProxyActionCallback 
{ 
    void DoProxyStuff(ServiceClient proxy); 
} 

void MyMethod(IProxyActionCallback callback) 
{ 
    try 
    { 
     ServiceClient proxy = new ServiceClient(); 
     proxy.ClientCredentials.UserName.UserName = "user"; 
     proxy.ClientCredentials.UserName.Password = "password"; 

     callback.DoProxyStuff(proxy); 

     proxy.Close(); 
    } 
    catch (FaultException ex) 
    { 
     // handle the exception  
    } 
} 

은 그럼 당신은 같은 메소드를 호출 : 그래서 당신은

class DoSpecificStuff : IProxyActionCallback 
{ 
    public void DoProxyStuff(ServiceClient proxy) 
    { 
     proxy.GetData(2); 
     if (proxy.State = CommunicationState.Opened) 
     { 
      proxy.GetData("data"); 
     } 
    } 
} 

: DoSpecificStuff 인터페이스를 구현하고 프록시와 특정 통화를 할 수있는 클래스가

MyMethod(new DoSpecificStuff()); 

인터페이스를 구현하는 많은 수의 클래스가 있으며 이들은 모두 한 곳에서 동일한 try-catch 보일러 플레이트 프록시 물건을 "공유"합니다.

관련 문제