Показать сообщение отдельно
Старый 24.01.2012, 00:09   #1  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
AX2012: сервисы и чудеса системного метода DictMethod.parameterCnt()
пытаюсь создать свой сервис и затем задеплоить его через сервисную группу, как написано в мануале What's New - Technical in Microsoft Dynamics® AX 2012 for Development в его 5 главе Chapter 5: Services and Application Integration.

Цитата:
Step by Step: Create the Data Contract Class
1.
Open Microsoft Dynamics AX 2012.
2.
Open a Developer workspace.
3.
Open the AOT.
4.
Create a new class named AddressFinder.
5.
Enhance the class by adding the [DataContractAttribute] attribute.
6.
Enter a method called Address which returns the address.
7.
Enhance the method by adding the [DataMemberAttribute] attribute.

X++:
[DataMemberAttribute] 
public str address() 
{
return "Demo Address"; 
}
Step by Step: Create the X++ Service Class
1.
Create a new class named AddressUtility. This is the service class.
2.
Create a public method named getNearestLocation. This method instantiates the AddressFinder object and returns the AddressFinder object.
3.
Enhance the class by adding the [SysEntryPointAttribute] attribute.

X++:
[SysEntryPointAttribute] 
public AddressFinder getNearestLocation() 
{ 
AddressFinder addressFinder = new AddressFinder(); 
return addressFinder; 
}
Step by Step: Create the Service
1.
Right-click the Services node in the AOT and select New Service.
2.
Change the Name property to AddressService.
3.
Set the Class property to AddressUtility.

4.
Expand the AddressService service node.
5.
Right-click the Operations node and select Add Operations.

6.
Check the Add checkbox and click OK.
7.
Right-click the Services Group node in the AOT and select New Service Group.
8.
Change the Name property to AddressServiceGroup.
9.
Drag the service under the service group node.
10.
Right-click the AddressServiceGroup service group and select Deploy service group.
на этой последней стадии получал ошибку о невалидности метода без какой бы то ни было дополнительной информации. по итогам дебаггинга немного докрутил метод в классе AifUtil.isValidDataMember, чтобы увидеть детали.

X++:
/// <summary>
///    Microsoft internal use only.
/// </summary>
/// <param name="dictMethod">An instance of the <c>SysDictMethod</c> class.</param>
/// <returns>A <c>boolean</c> Enumeration Type.</returns>
static boolean isValidDataMember(SysDictMethod dictMethod)
{
    // Alex Voytsekhovskiy (WMP) (2012/01/20) (Demande #)
    //-->
    Types   retType, parType;
    int     retId, parId;
    int     parCnt;
    boolean res, allRes;
    str     msg;
    ;
    res = dictMethod.compiledOk();
    if (!res)
    {
        msg = "Not complied";
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        

    res = dictMethod.utilElementType() == UtilElementType::ClassInstanceMethod;
    if (!res)
    {    
        msg = "Not ClassInstanceMethod";
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        

    res = dictMethod.accessSpecifier() == AccessSpecifier::public;
    if (!res)
    {    
        msg = "Not Public method";
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        
    parCnt = dictMethod.parameterCnt();
    res =parCnt == 1;
    if (!res)
    {    
        msg = strFmt("Not One and only one input parameter = %1", parCnt);
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        

    res = dictMethod.parameterOptional(1);
    if (!res)
    {    
        msg = "Parameter is not optional";
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        
    retType = dictMethod.returnType();
    parType = dictMethod.parameterType(1);
    res = retType == parType;
    if (!res)
    {        
        msg = strfmt("Return type %1 does not match parameter type %2", retType, parType);
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        
    retId = dictMethod.returnId();
    parId = dictMethod.parameterId(1);
    res = retId == parId;
    if (!res)
    {    
        msg = msg+"; "+ strfmt("Return Id %1 does not match parameter id %2", retId, parId);
        throw error(strfmt("%1.%2() is not valid DataMember; Errors: %3", dictMethod.parentName(), dictMethod.name(), msg));
    }        

    return res;
    //<--

//    return (
//        dictMethod.compiledOk() &&                                                  // Compile OK
//        dictMethod.utilElementType() == UtilElementType::ClassInstanceMethod &&     // Instance method
//        dictMethod.accessSpecifier() == AccessSpecifier::public &&                  // Public method
//        dictMethod.parameterCnt() == 1  &&                                          // One and only one input parameter
//        dictMethod.parameterOptional(1) &&                                          // Parameter is optional
//        dictMethod.returnType() == dictMethod.parameterType(1) &&                   // Return type matches parameter type
//        dictMethod.returnId() == dictMethod.parameterId(1));
}
сам метод, который не проходит проверку на количество параметров, вот:

X++:
[DataMemberAttribute]
public str address1(str s ='')
{
    return "Demo Address";
}
при этом дебаггер показывает следующее:
Нажмите на изображение для увеличения
Название: 2012-01-23_1449.png
Просмотров: 622
Размер:	72.0 Кб
ID:	7496

шутки ради нарисовал рядышком ещё один метод -- однояйцевый близнец предыдущего

X++:
[DataMemberAttribute]
str gimme(str s = '')
{
    ;
    return "gimme more";
}
с ним ошибок не возникает, и количество параметров = 1.

в этой связи вопрос: куда копать, и зачем методам, который выставляются через сервис вообще нужны параметры? (обратите внимание на проверки в методе)

компиляция, forward compilation, CIL, перезапуск клиента, сервера и прочие танцы с бубном уже исполнялись. спасибо.
__________________
Felix nihil admirari