EF中linq expression func<Func<T,bool>gt;动态查询怎么写

C#可以编写一个方法对T表查询并返回List&T&吗_百度知道
C#可以编写一个方法对T表查询并返回List&T&吗
,我只需要用一个这个方法就查询这10个表??,能实现不;T?)?,bool&gt。如何编写这样的一个方法;(;T&T& GetXXXXX&lt:public List&lt:Func&lt?但是方法要怎么写?的内容也许可以是?; func吧;返回的结果是我给定的T类型如果我表里面有10个表用的是 linq to entities
提问者采纳
T, out string msg)其中DataInitializer&lt,用来把数据库中的数据装到List&这样的类;中2)这只是个例子;T&gt,我的库里大概有20个表;K&gt,感觉有点相似, DataInitializer& GetTable(K key,用来在初始化是去数据库中取出不同的数据TableFormer dataFormer 这也是一个委托的实例;T&gt,如果发现内存中没有我要的数据,目的是通过此类中的方法实现对内存数据增删查改, TableFormer dataF GetData 是一个委托的实例,用来查找数据,我没太明白你所说的内容我不知道你说的是不是我现在所做的,K&gt,我想把我做的描述下;K&gt。我定义了一个public class MDB& GetData,所有的操作都是通过这个类里的方法统一完成的(也就是说我用同一个方法完成了所有表相同的操作)这个类的内容中有类似如下方法的很多方法1)public MDBData&lt,将会到数据库中查找,你可以在这个类里写删除 和修改的方法
饿,我没看懂啊,能说简单点吗?比如我有一个Product表和一个Customer表,能否只用一个方法比如说public List&T& Query&T&(Expression&Func&T,bool&& where)这样的方法,然后我调用的时候就:List&Product& p = Query&Product&(expr) 或者List&Customer& p = Query&Customer&(expr) 就可以取得Product表和Customer表的内容。
就我对“linq 到对象”的了解,想通过传lambda表达式来完成你的想法是不行的。因为所有linq到对象的方法都是扩展方法,这些方法的施用对象是已经存在于内存中的集合,如果你在内存中已经存在某种集合你可以通过linq到对象来对此集合(已实现IEnumerable&T&)进行操作,但是如果你想通过传递lambda来从数据库捞取数据恐怕要用到linq to sql,很惭愧我对linq to sql 也不熟悉。如果你把参数定义成委托的话应该也可以实现,当你实例化的时候不是传递一个lambda,而是一个告诉Query&T&如何从数据库读取数据的方法,方法里面要实现具体的数据库连接等操作,那不就实现了吗
提问者评价
虽不明,但觉厉。我已经放弃这种想法了,好像没有找到方法,ObjectSet&T&也是行不通的……
其他类似问题
为您推荐:
其他2条回答
(from t1 in Table1select t1).Concat(from t2 in Table2select t2).Concat依此类推当然你也可以用Expression Tree自己做查询,具体你要看msdn了
尝试过了,没有成功,不太容易。假设你有一张表:Person,那么用EntityFramework的情况下,只要用:entities.Person.ToList&Person&();不就可以了,这个本身就是泛型方法啊。
那我要where呢,怎么办?而且主要是添加修改删除记录方面,我想3个方法直接能通用添加、修改、删除所有的表……其实还是3层架构的问题,我想尝试分层来做,于是就…………
EntityFramework或者Linq都不需要再分层了,他们本身就已经分层了:业务层+数据访问层
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁Posts - 269,
Articles - 0,
Comments - 1983
13:34 by 破狼, ... 阅读,
&&&&&&& 在中我留下了一个问题就是PredicateExtensions。在这里很简单不需要什么多的基础只要比会And、Or逻辑运算数学知识就够了。
先贴上代码好分析:
public&static&class&PredicateExtensions&&&&{&&&&&&&&public&static&Expression&Func&T,&bool&&&True&T&()&{&return&f&=&&true;&}&&&&&&&&public&static&Expression&Func&T,&bool&&&False&T&()&{&return&f&=&&false;&}&&&&&&&&public&static&Expression&Func&T,&bool&&&Or&T&(this&Expression&Func&T,&bool&&&expression1,&&&&&&&&&&&&Expression&Func&T,&bool&&&expression2)&&&&&&&&{&&&&&&&&&&&&var&invokedExpression&=&Expression.Invoke(expression2,&expression1.Parameters&&&&&&&&&&&&&&&&&&&&.Cast&Expression&());&&&&&&&&&&&&return&Expression.Lambda&Func&T,&bool&&(Expression.Or(expression1.Body,&invokedExpression),&&&&&&&&&&&&expression1.Parameters);&&&&&&&&}&&&&&&&&public&static&Expression&Func&T,&bool&&&And&T&(this&Expression&Func&T,&bool&&&expression1,&&&&&&&&&&&&&&&Expression&Func&T,&bool&&&expression2)&&&&&&&&{&&&&&&&&&&&&var&invokedExpression&=&Expression.Invoke(expression2,&expression1.Parameters&&&&&&&&&&&&&&&&&.Cast&Expression&());&&&&&&&&&&&&return&Expression.Lambda&Func&T,&bool&&(Expression.And(expression1.Body,&&&&&&&&&&&&&&&&&&&&invokedExpression),&expression1.Parameters);&&&&&&&&}&&&&}
&&&&& 在其中只有四个方法,True、False、Or、And,一看大家就知道这里是对逻辑运算操作。其中True、False是对表达式进行初始化,在我没有看见这个类之前我用的是null,用null这要在没有And,Or逻辑操作时进行Null判断,如果null则返回后一个表达式。而在这里有了true,fakse这相当于初始化了一个表达式,就不用再那么麻烦了。
&&&& True、False的初始化有一个规则就是不能影响我们的正常表达式.在我们刚学语言的时候就有:逻辑与一假为假,逻辑或一真为真,那这句就可以运用于我们的这两表达式的初始化了。当我们在True、False初始化表达式和后便连接的表达式逻辑运算为And时候,我们就该用True,这么这个逻辑条件的真假取决于我们的后面表达式(逻辑与一假为假,一真那么还不确定),是不是没有影响我们的正常表达式?同理逻辑运算为Or时候,就该用False(逻辑或一真为真,一假也不确定,就取决于另一个表达式)。是不是很简单,还是那句话,我这种鼠辈估计很难想到,是应试教育禁锢了我们的思维啊!
&&&&& And、Or这是表达式逻辑运算连接,那主体为取出左边表达式body Invoke了再与右边表达式连接返回。
&&&& 为了验证我的结论,我们做几个小测试(这里为了方便改为了控制台程序):
测试1:True and连接;
public&static&void&Test1()&&&&&&&&{&&&&&&&&&&&&DbDataContext&db&=&new&DbDataContext();&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressleft&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PredicateExtensions.True&TemplateDocument&();&&&&&&&&&&&&expressleft&=&expressleft.And(t&=&&t.CategoriesID&&&<span style="color: #);&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressright&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PredicateExtensions.True&TemplateDocument&();&&&&&&&&&&&&expressright&=&expressright.And(t&=&&t.CategoriesID&&&<span style="color: #);&&&&&&&&&&expressleft=&&expressleft.Or(expressright);&&&&&&&&&&var&sql&=&db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t&=&&new&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&t.TemplateID,&t.TemplateName,&t.CategoriesID&})).CommandT&&&&&&&&&&&&Console.WriteLine(sql);&&&&&&&&}
SELECT&[t0].[TemplateID],&[t0].[TemplateName],&[t0].[CategoriesID]&FROM&[dbo].[TemplateDocument]&AS&[t0]&WHERE&([t0].[CategoriesID]&&&@p0)&OR&([t0].[CategoriesID]&&&@p1)
不知你发现没有Linq表达式已经把True条件智能的去掉了,(True&&XX1)||(True&&XX2) = XX1||XX2。按照上面的说法,那我们把第一个条件改为False 的Or连接也应该一样,测试一下:测试2
public&static&void&Test2()&&&&&&&&{&&&&&&&&&&&&DbDataContext&db&=&new&DbDataContext();&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressleft&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PredicateExtensions.False&TemplateDocument&();//上例True该为False&&&&&&&&&&&&expressleft&=&expressleft.Or(t&=&&t.CategoriesID&&&<span style="color: #);//上例And该为Or&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressright&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PredicateExtensions.False&TemplateDocument&();&&&&&&&&&&&&&&&&&&&&&&&&&&//上例True该为False&&&&&&&&&&&&expressright&=&expressright.Or(t&=&&t.CategoriesID&&&<span style="color: #);&&&&&&&&&&&&&&&&&&&&&&&&&&//上例And该为Or&&&&&&&&&&&&expressleft&=&expressleft.Or(expressright);&&&&&&&&&&&&var&sql&=&db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t&=&&new&{&&&&&&&&&&&&&&&&&&&&&&&&&&t.TemplateID,&t.TemplateName,&t.CategoriesID&})).CommandT&&&&&&&&&&&&Console.WriteLine(sql);&&&&&&&&}
SELECT&[t0].[TemplateID],&[t0].[TemplateName],&[t0].[CategoriesID]&FROM&[dbo].[TemplateDocument]&AS&[t0]WHERE&([t0].[CategoriesID]&&&@p0)&OR&([t0].[CategoriesID]&&&@p1)
和上例输出了sql完全一样,,(False||XX1)||(False||XX2) = XX1||XX2。那我们改变用法将True或Or连接呢?测试3:
public&static&void&Test3()&&&&&&&&{&&&&&&&&&&&&DbDataContext&db&=&new&DbDataContext();&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressleft&=&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PredicateExtensions.True&TemplateDocument&();&&&&&&&&&&&&expressleft&=&expressleft.Or(t&=&&t.CategoriesID&&&<span style="color: #);&&&&&&&&&&&&Expression&Func&TemplateDocument,&bool&&&expressright&=&&&&&&&&&&&&&&&&&PredicateExtensions.False&TemplateDocument&();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&expressright&=&expressright.Or(t&=&&t.CategoriesID&&&<span style="color: #);&&&&&&&&&&&&expressleft&=&expressleft.And(expressright);&&&&&&&&&&&&var&sql&=&db.GetCommand(db.TemplateDocument.Where(expressleft).Select(t&=&&new&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&t.TemplateID,&t.TemplateName,&t.CategoriesID&})).CommandT&&&&&&&&&&&&Console.WriteLine(sql);&&&&&&&&}
SELECT&[t0].[TemplateID],&[t0].[TemplateName],&[t0].[CategoriesID]&FROM&[dbo].[TemplateDocument]&AS&[t0]&WHERE&[t0].[CategoriesID]&&&@p0&
&恩 只有一个表达式了,当然了啊,你第一个表达式是(True||XX1)&&(False||XX2) = True&&XX2=XX2.做了这个测试,我真的很佩服微软,在代码中能够这么智能判断。索性把条件完全弄掉,我们把中间的And改为Or:(True||XX1)||(False||XX2) = True||XX2=True。这个就自己测试了你将看不到where条件了。 在中给出了一个结果总结.
& 1:构造函数使用True时:单个AND有效,多个AND有效;单个OR无效,多个OR无效;混合时写在AND后的OR有效 & 2:构造函数使用False时:单个AND无效,多个AND无效;单个OR有效,多个OR有效;混合时写在OR后面的AND有效
我们来验证验证:
1构造函数使用True时:
(1):单个AND有效,多个AND有效,当然了True&&XX=XX
(2):单个OR无效,多个OR无效:True || XX=True所以无效。
(3):混合时写在AND后的OR有效:(True&&XX)||XX1=XX||XX1有效,(True||XX)&&XX1=True&&XX1=XX1,肖博前辈说的无效(相对于我们需要的表达式无效,其实还是有效) (True||XX)||XX1=True||XX1=True(这里你不会看见where条件)。
2:构造函数使用False时:
&& 和True情况一样,我就不去推导了,偷个懒。
以上全是个人意见,如果有什么不对了请指导,更正。binder 原理及实现机制&一&
0,从android native service 说起我们先来看一个简单的 native service 例子:// 定义能力接口class IBuddy: public IInterface {public:
BUDDY_GET_PID = IBinder::FIRST_CALL_TRANSACTION,
virtual int getPid(void ) = 0;
DECLARE_META_INTERFACE(Buddy);};IMPLEMENT_META_INTERFACE(Buddy, &Buddy&);// 定义接口proxy ,用于应用调用接口class BpBuddy : public BpInterface&IBuddy& {public:
// 定义构造函数,注意参数 类型
BpBuddy(const sp&IBinder&& impl) : BpInterface&IBuddy&(impl) { }
virtual void getPid(int32_t push_data) {
Parcel data,
// Write RPC headers.
(previously just the interface token)
data.writeInterfaceToken(IBuddy::getInterfaceDescriptor());
data.writeInt32(push_data);
remote()-&transact(BUDDY_GET_PID, data, &reply);
status_t status = reply.readInt32(&res);
}}// 接口的实现类class BnBuddy : public BnInterface&IBuddy& {
virtual status_t onTransact(uint32_t code,const Parcel& data,
Parcel* reply,uint32_t flags = 0);};status_t BnBuddy::onTransact(uint32_t code, const Parcel &data,
Parcel* reply,uint32_t flags) {
// 检测 discriptor 是否相同
CHECK_INTERFACE(IBuddy, data, reply);
switch(code) {
case BUDDY_GET_PID: {
int32_t pid = getPid();
// 调用getPid() 函数
reply-&writeInt32(pid);
return NO_ERROR;
return BBinder::onTransact(code, data, reply, flags);
}}class BuddyService : public BnBuddy {
virtual int32_t getPid() {// impl:
system call, get process ID
return getpid();
}};int main(int argc, char **argv){
//regester service to service manager
defaultServiceManager()-&addService(String16(&BuddyService&), new BuddyService());
ProcessState::self()-&startThreadPool();
IPCThreadState::self()-&joinThreadPool();
return 0;}sp&IServiceManager& sm =defaultServiceManager();// find buddy service , and call functionsp&IBinder& binder =sm-&getService(String16(&Buddy&));sp&IBuddy& mBuddy =interface_cast&IBuddy&(binder);0.1 一个完整native service 所需要的组件(class)0.2 注册service 到系统再来回顾一下 前面添加service 代码:int main(int argc, char **argv){
//regester service to service manager
defaultServiceManager()-&addService(String16(&BuddyService&), new BuddyService());
//开启监听
ProcessState::self()-&startThreadPool();
IPCThreadState::self()-&joinThreadPool();
return 0;}RTFSC , 源代码我们逐步分析: 第一步,首先调用 defaultServiceManager(),此函数调用返回了一个 IServiceManager 指针,sp&IServiceManager& defaultServiceManager(){
gDefaultServiceManager
在文件 /android/frameworks/native/libs/binder/Static.cpp
if (gDefaultServiceManager != NULL) return gDefaultServiceM
// 加锁 线程安全
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
// 这里是我们所需要关注的重点,这行代码这里发生了什么呢 ?
gDefaultServiceManager = interface_cast&IServiceManager&(
ProcessState::self()-&getContextObject(NULL));
if (gDefaultServiceManager == NULL)
return gDefaultServiceM}// 这里是一个singleton, gProcess 也是在
/android/frameworks/native/libs/binder/Static.cpp
中定义的sp&ProcessState& ProcessState::self(){
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
gProcess = new ProcessS
return gP}sp&IBinder& ProcessState::getContextObject(const sp&IBinder&& caller){
return getStrongProxyForHandle(0);}sp&IBinder& ProcessState::getStrongProxyForHandle(int32_t handle){
sp&IBinder&
AutoMutex _l(mLock);
// 查找 handle entry
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e-&
if (b == NULL || !e-&refs-&attemptIncWeak(this)) {
if (handle == 0) {
status_t status = IPCThreadState::self()-&transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
// 这里我们返回的是一个 handle
== 0 的BpBinder
b = new BpBinder(handle);
e-&binder =
if (b) e-&refs = b-&getWeakRefs();
result.force_set(b);
e-&refs-&decWeak(this);
}}interface_cast&IServiceManager& 这个函数的作用是什么呢? template&typename INTERFACE&inline sp&INTERFACE& interface_cast(const sp&IBinder&& obj){
return INTERFACE::asInterface(obj);}显然,这里直接调用的 IServiceManager::asInterface 那么函数asInterface 是在哪里声明和定义的呢,下面我们看看 IServiceManager 这个类的定义// IServiceManager 声明class IServiceManager : public IInterface{public:
DECLARE_META_INTERFACE(ServiceManager);
//。。。 省略不相关代码};// 定义IMPLEMENT_META_INTERFACE(ServiceManager, &android.os.IServiceManager&);0.2.0 关于 IInterface 所提供的两个宏 // 定义了一个 静态变量// 声明了一个 asInterface 静态函数// 声明了一个获取接口描述符的成员函数#define DECLARE_META_INTERFACE(INTERFACE)
static const android::String16
static android::sp&I##INTERFACE& asInterface(
const android::sp&android::IBinder&& obj);
virtual const android::String16& getInterfaceDescriptor()
I##INTERFACE();
virtual ~I##INTERFACE();
/#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)
// 初始化了类的静态变量
const android::String16 I##INTERFACE::descriptor(NAME);
// 静态函数返回的就是描述符静态变量
const android::String16&
I##INTERFACE::getInterfaceDescriptor() const {
return I##INTERFACE::
// asInterface 函数的实现 , 在IServiceManager 中这里的参数是一个 BpBinder
android::sp&I##INTERFACE& I##INTERFACE::asInterface(
const android::sp&android::IBinder&& obj)
android::sp&I##INTERFACE&
if (obj != NULL) {
intr = static_cast&I##INTERFACE*&(
obj-&queryLocalInterface(
I##INTERFACE::descriptor).get());
if (intr == NULL) {
intr = new Bp##INTERFACE(obj);
I##INTERFACE::I##INTERFACE() { }
I##INTERFACE::~I##INTERFACE() { }
/#define CHECK_INTERFACE(interface, data, reply)
if (!data.checkInterface(this)) { return PERMISSION_DENIED; }
/template&typename INTERFACE&inline sp&INTERFACE& interface_cast(const sp&IBinder&& obj){
return INTERFACE::asInterface(obj);}&因此 interface_cast&IServiceManager&( ProcessState::self()-&getContextObject(NULL));& 返回的是一个 BpServiceManager(BpBinder)// android/frameworks/native/libs/binder/IServiceManager.cppvirtual status_t addService(const String16& name, const sp&IBinder&& service, bool allowIsolated){
Parcel data,
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
// 调用BpBinder::transact
status_t err = remote()-&transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() :}第二步:IPCThreadState::self()-&joinThreadPool();void IPCThreadState::joinThreadPool(bool isMain = true){
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
//...............
// 循环接收请求数据
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
if (result & NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
} while (result != -ECONNREFUSED && result != -EBADF);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);}status_t IPCThreadState::getAndExecuteCommand(){
result = talkWithDriver();
if (result &= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN & sizeof(int32_t))
cmd = mIn.readInt32();
result = executeCommand(cmd);
//...............
}}第三步:ProcessState::self()-&startThreadPool();void ProcessState::startThreadPool(){
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted =
spawnPooledThread(true);
}}String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
name.appendFormat(&Binder_%X&, s);}void ProcessState::spawnPooledThread(bool isMain){
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV(&Spawning new pooled thread, name=%s/n&, name.string());
sp&Thread& t = new PoolThread(isMain);
t-&run(name.string());
}}class PoolThread : public Thread{public:
PoolThread(bool isMain)
: mIsMain(isMain)
protected:
virtual bool threadLoop()
IPCThreadState::self()-&joinThreadPool(mIsMain);
const bool mIsM};0.3 通过service& manager 获取服务我们看一下下面这段代码sp&IServiceManager& sm =defaultServiceManager();// find buddy service , and call functionsp&IBinder& binder =sm-&getService(String16(&Buddy&));sp&IBuddy& mBuddy =interface_cast&IBuddy&(binder);看到以上的代码,和 defaultServiceManager& 获取 IServiceManager 的内容差不多,在这里不在赘述,关于 getService 及addService的实现过程,后面会讲到。1,ServiceManager&&&&&&& 在前面 native service 例子中,我们已经看到,要将用户自定义的& native service ,添加到系统及从系统获取自定义service, 都和一个类分不开,IServiceManager,IServiceManager 是应用层实现binder通信的基础,首先,看一下 IServiceManager 类图,部分细节为画出,请参见native service 的类图。&&&&&& 显然,这里并没有如我们预想的看到& BnServiceManager 这个类,那么他在哪儿呢 ?在我的平台的源代码里,其实是有BnServiceManager这个类,只是没有画出来,为什么没有画出来呢,回想前面讲到过的,IServiceManager 对象构造时候,传入的参数是 BpBinder,而ServiceManager 因为其特殊性,不是使用的BnXXX的方式,因此,BnServiceManager 这个类,并没有被真正的使用过,可能是处于给开发者作为一个例子参考的考虑。1,1 serviceManager proxy端&&&&&&& BpServiceManager& 是IServiceManager 的接口的proxy,由类图可知,IServiceManager 一共有四个接口。主要功能也就是为了管理系统的service。BpServiceManager 的mRemote 是一个BpBinder ,而并不是 BnServiceManager,因为IServciceManager 除了完成接口提供的函数外,因为她是用来维护整个的service 系统的,所以BpBinder 里,还有许多与IPC 关于的代码。为了更进一步的了解BpBinder,我们选择IServiceManager 里使用最多的两个 接口 addService& 和 getService 来进行 细致的讲解。virtual status_t BpServiceManager::addService(const String16& name, const sp&IBinder&& service,
bool allowIsolated = false){
// Parce 在使用 binder 进行IPC时候,一个很重要的数据结构,在此不表,后文讲解
Parcel data,
// 写入接口描述符
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
// 写入servcie name
data.writeString16(name);
// 写如service 的 实例,
这里很重要,后面的实例,IPC 全靠他了。
data.writeStrongBinder(service);
// 写入isolate 的
data.writeInt32(allowIsolated ? 1 : 0);
// 调用 BpBinder的 transact 函数,关于常量定义
// GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
// CHECK_SERVICE_TRANSACTION,
// ADD_SERVICE_TRANSACTION,
// LIST_SERVICES_TRANSACTION,
status_t err = remote()-&transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() :}status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0){
// Once a binder has died, it will never come back to life.
// 构造函数初始化, mAlive == 0, mHandle == 0, flags == 0, default
if (mAlive) {
// 这里调用到了IPCThreadState
status_t status = IPCThreadState::self()-&transact(mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return DEAD_OBJECT;}看看 IPCThreadState里的实现status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags){
status_t err = data.errorCheck();
// 常量定义,此定义在 /kernel/drivers/staging/android/binder.h中定义
//enum transaction_flags {
//TF_ONE_WAY
/* this is a one-way call: async, no return */
//TF_ROOT_OBJECT
/* contents are the component&#39;s root object */
//TF_STATUS_CODE
/* contents are a 32-bit status code */
//TF_ACCEPT_FDS
/* allow replies with file descriptors */
flags |= TF_ACCEPT_FDS;
if (err == NO_ERROR) {
// 将数据写入mOut中,同样在kernel source中定义
BC_TRANSACTION = _IOW(&#39;c&#39;, 0, struct binder_transaction_data),
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
if (err != NO_ERROR) {
if (reply) reply-&setError(err);
return (mLastError = err);
if ((flags & TF_ONE_WAY) == 0) {
if (reply) { // reply != NULL;
err = waitForResponse(reply);
Parcel fakeR
err = waitForResponse(&fakeReply);
err = waitForResponse(NULL, NULL);
}}writeTransactionData 函数,将请求的数据,打包到parcel中。status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer){
binder_transaction_
tr.target.handle = // 0
tr.code = // ADD_SERVICE_TRANSACTION
tr.flags = binderF
flags == 0|TF_ACCEPT_FDS;
tr.cookie = 0;
tr.sender_pid = 0;
tr.sender_euid = 0;
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize();
tr.data.ptr.buffer = data.ipcData();
tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t);
tr.data.ptr.offsets = data.ipcObjects();
} else if (statusBuffer) {// but
statusBuffer == NULL;
tr.flags |= TF_STATUS_CODE;
*statusBuffer =
tr.data_size = sizeof(status_t);
tr.data.ptr.buffer = statusB
tr.offsets_size = 0;
tr.data.ptr.offsets = NULL;
return (mLastError = err);
// BC_TRANSACTION == cmd
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
return NO_ERROR;}打包的数据结构,binder_transaction_data在 /kernel/drivers/staging/android/binder.h中定义 ,这是binder IPC 中,几个关键的数据结构之一,在后面还会讲到binder_write_read& 和& flat_binder_object,都在 内核的 binder.h里定义的struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
/* target descriptor of command transaction */
/* target descriptor of return transaction */
/* target object cookie */
/* transaction command */
/* General information about the transaction. */
/* number of bytes of data */
/* number of bytes of offsets */
/* If this transaction is inline, the data immediately
* otherwise, it ends with a pointer to
* the data buffer.
/* transaction data */
const void
/* offsets from buffer to flat_binder_object structs */
const void
}};waitForResponse 函数,函数名字有点歧义,准确的说,应该是transAndWait,将数据写入binder driver 并等待binder driver 响应数据。status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult=NULL){
while (1) {
if ((err=talkWithDriver()) & NO_ERROR)
// talkWithDriver
返回以后,读出返回的数据,在 mIn中
err = mIn.errorCheck();
if (err & NO_ERROR)
if (mIn.dataAvail() == 0)
// 读取响应消息类型
cmd = mIn.readInt32();
switch (cmd) {
//........................
case BR_REPLY:
binder_transaction_
err = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(err == NO_ERROR, &Not enough command data for brREPLY&);
if (err != NO_ERROR)
if (reply) {
if ((tr.flags & TF_STATUS_CODE) == 0) {
// 将响应数据填充到 parcel
reply-&ipcSetDataReference(
reinterpret_cast&const uint8_t*&(tr.data.ptr.buffer), tr.data_size,
reinterpret_cast&const size_t*&(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t),
freeBuffer, this);
//.......................
//........................
err = executeCommand(cmd);
if (err != NO_ERROR)
if (err != NO_ERROR) {
if (acquireResult) *acquireResult =
if (reply) reply-&setError(err);
mLastError =
}}talkWithDriver,顾名思义,通过此函数,与binder driver 进行对话。status_t IPCThreadState::talkWithDriver(bool doReceive = true){
if (mProcess-&mDriverFD &= 0) {
return -EBADF;
// 数据结构 定义在 kernel中,
/kernel/drivers/staging/android/binder.h
binder_write_
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() &= mIn.dataSize();
// We don&#39;t want to write anything if we are still reading
// from data left in the input buffer and the caller
// has requested to read the next data.
writeTransactionData 中写入的值
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
bwr.write_size = outA
bwr.write_buffer = (long unsigned int)mOut.data();
// This is what we&#39;ll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (long unsigned int)mIn.data();
bwr.read_size = 0;
bwr.read_buffer = 0;
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
// 写数据同时等待读数据,阻塞
if (ioctl(mProcess-&mDriverFD, BINDER_WRITE_READ, &bwr) &= 0)
err = NO_ERROR;
// 在IPCThreadState构造函数处初始化
open_driver
if (mProcess-&mDriverFD &= 0) {
err = -EBADF;
} while (err == -EINTR);
if (err &= NO_ERROR) {
//reset mOut
if (bwr.write_consumed & 0) {
if (bwr.write_consumed & (ssize_t)mOut.dataSize())
mOut.remove(0, bwr.write_consumed);
mOut.setDataSize(0);
// 将返回的数据写入
if (bwr.read_consumed & 0) {
mIn.setDataSize(bwr.read_consumed);
mIn.setDataPosition(0);
return NO_ERROR;
}}与binder driver 通信的时候,实际用到的数据结构/* * On 64-bit platforms where user code may run in 32-bits the driver must * translate the buffer (and local binder) addresses apropriately. */// 利用整型与指针(实际上就是一个整型的数值,只不过其数值表示的是内存地址)之间的联系,// 简单粗暴且高效的读写方式struct binder_write_read {
signed long
/* bytes to write */
signed long
/* bytes consumed by driver */
unsigned long
signed long
/* bytes to read */
signed long
/* bytes consumed by driver */
unsigned long
read_};作为server(BuddyService) 端,当开启线程以后,会等待从binder driver 读取消息,然后解析消息并响应响应的数据,下面是执行解析和响应的函数executeCommandstatus_t IPCThreadState::executeCommand(int32_t cmd){
RefBase::weakref_type*
status_t result = NO_ERROR;
switch (cmd) {
//...... 省略部分代码
case BR_TRANSACTION:
binder_transaction_
// 读取从 binder driver 获取到的数据 tr
result = mIn.read(&tr, sizeof(tr));
ALOG_ASSERT(result == NO_ERROR,&Not enough command data for brTRANSACTION&);
if (result != NO_ERROR)
buffer.ipcSetDataReference(
reinterpret_cast&const uint8_t*&(tr.data.ptr.buffer), tr.data_size,
reinterpret_cast&const size_t*&(tr.data.ptr.offsets), tr.offsets_size/sizeof(size_t),
freeBuffer, this);
const pid_t origPid = mCallingP
const uid_t origUid = mCallingU
mCallingPid = tr.sender_
mCallingUid = tr.sender_
//..................
if (tr.target.ptr) {
// BBinder:: transact ==& BuddyService::onTransact
sp&BBinder& b((BBinder*)tr.cookie);
const status_t error = b-&transact(tr.code, buffer, &reply, tr.flags);
if (error & NO_ERROR) reply.setError(error);
const status_t error = the_context_object-&transact(tr.code, buffer, &reply, tr.flags);
if (error & NO_ERROR) reply.setError(error);
if ((tr.flags & TF_ONE_WAY) == 0) {
// server 发送响应
sendReply(reply, 0);
mCallingPid = origP
mCallingUid = origU
//...... 省略部分代码
result = UNKNOWN_ERROR;
if (result != NO_ERROR) {
mLastError =
} }status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags){
status_t statusB
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err & NO_ERROR)
return waitForResponse(NULL, NULL);}getService 从 serviceManager& 获取服务virtual sp&IBinder& BpServiceManager::getService(const String16& name) const{
for (n = 0; n & 5; n++){
sp&IBinder& svc = checkService(name);
if (svc != NULL)
ALOGI(&Waiting for service %s.../n&, String8(name).string());
return NULL;}virtual sp&IBinder& checkService( const String16& name) const{
Parcel data,
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()-&transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();}调用的是checkService ,而 里面同样的调用的是 remote()-&transact 这里不在赘述其调用过程,这里我们要说的 reply.readStrongBinder();1.2 client 与server 通信中一个重要的数据结构 parcel.parcel 里面定义了很多数据接口,因为代码长度关系,我们选择几个 经常使用的,重要的 接口分析一下status_t Parcel::writeInterfaceToken(const String16& interface){
writeInt32(IPCThreadState::self()-&getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER);
// currently the interface identification token is just its name as a string
return writeString16(interface);}status_t Parcel::writeStrongBinder(const sp&IBinder&& val){
return flatten_binder(ProcessState::self(), val, this);}status_t flatten_binder(const sp&ProcessState&& proc, const sp&IBinder&& binder, Parcel* out){
flat_binder_
obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
// BnBuddy::localBinder {}.
BpBinder::remoteBinder{}.
IBinder *local = binder-&localBinder();
if (!local) {
BpBinder *proxy = binder-&remoteBinder();
if (proxy == NULL) {
ALOGE(&null proxy&);
const int32_t handle = proxy ? proxy-&handle() : 0;
obj.type = BINDER_TYPE_HANDLE;
obj.handle =
obj.cookie = NULL;
obj.type = BINDER_TYPE_BINDER;
obj.binder = local-&getWeakRefs();
obj.cookie =
obj.type = BINDER_TYPE_BINDER;
obj.binder = NULL;
obj.cookie = NULL;
return finish_flatten_binder(binder, obj, out);}inline static status_t finish_flatten_binder(const sp&IBinder&& binder, const flat_binder_object& flat, Parcel* out){
return out-&writeObject(flat, false);}sp&IBinder& Parcel::readStrongBinder() const{
sp&IBinder&
unflatten_binder(ProcessState::self(), *this, &val);}status_t unflatten_binder(const sp&ProcessState&& proc, const Parcel& in, sp&IBinder&* out){
const flat_binder_object* flat = in.readObject(false);
if (flat) {
switch (flat-&type) {
case BINDER_TYPE_BINDER:
*out = static_cast&IBinder*&(flat-&cookie);
return finish_unflatten_binder(NULL, *flat, in);
case BINDER_TYPE_HANDLE:
*out = proc-&getStrongProxyForHandle(flat-&handle);
return finish_unflatten_binder(
static_cast&BpBinder*&(out-&get()), *flat, in);
return BAD_TYPE;}1.3 serviceManager impl 端//android/frameworks/native/cmds/servicemanager/service_manager.cint main(int argc, char **argv){
// struct binder_state
struct binder_state *
///* the one magic object */
//#define BINDER_SERVICE_MANAGER ((void*) 0)
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
//初始化 binder_node 根节点
if (binder_become_context_manager(bs)) {
ALOGE(&cannot become context manager (%s)/n&, strerror(errno));
return -1;
svcmgr_handle =
binder_loop(bs, svcmgr_handler);
return 0;}struct binder_state *binder_open(unsigned mapsize){
struct binder_state *
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
// 获取 fd
bs-&fd = open(&/dev/binder&, O_RDWR);
if (bs-&fd & 0) {
fprintf(stderr,&binder: cannot open device (%s)/n&,
strerror(errno));
goto fail_
// 映射内存大小
bs-&mapsize =
// 映射内存
bs-&mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs-&fd, 0);
if (bs-&mapped == MAP_FAILED) {
fprintf(stderr,&binder: cannot map device (%s)/n&,
strerror(errno));
goto fail_
//..............}void binder_loop(struct binder_state *bs, binder_handler func){
struct binder_write_
// 4X32 字节的缓冲区
unsigned readbuf[32];
不写数据,只是读数据,所以都为 0
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
// 告诉驱动程序开始进入循环监听,读取数据
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned)
res = ioctl(bs-&fd, BINDER_WRITE_READ, &bwr);
if (res & 0) {
ALOGE(&binder_loop: ioctl failed (%s)/n&, strerror(errno));
// 解析读取到的数据
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
if (res == 0) {
ALOGE(&binder_loop: unexpected reply?!/n&);
if (res & 0) {
ALOGE(&binder_loop: io error %d %s/n&, res, strerror(errno));
}}int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func){
int r = 1;
//size 是按 字节算的
uint32_t *end = ptr + (size / 4);
while (ptr & end) {
// mOut.writeInt32(cmd);
// mOut.write(&tr, sizeof(tr));
uint32_t cmd = *ptr++;
// ++ 以后
ptr 指向了 这样的一个数据结构
binder_transaction_data tr
switch(cmd) {
//...................................
case BR_TRANSACTION: {
// binder_txn 与 binder_transaction_data 但是,两个数据结构的内存结构相同,
struct binder_txn *txn = (void *)
if ((end - ptr) * sizeof(uint32_t) & sizeof(struct binder_txn)) {
ALOGE(&parse: txn too small!/n&);
return -1;
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
// 64 &#215; 4
//struct binder_io//{//
/* pointer to read/write from *///
uint32_t *
/* array of offsets *///
uint32_t data_
/* bytes available in data buffer *///
uint32_t offs_
/* entries available in offsets array */////
char *data0;
/* start of data buffer *///
uint32_t *offs0;
/* start of offsets buffer *///
uint32_//};
struct binder_
struct binder_
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
call back svcmgr_handler
res = func(bs, txn, &msg, &reply);
// send reply ==&binder_write==&ioctl.
binder_send_reply(bs, &reply, txn-&data, res);
ptr += sizeof(*txn) / sizeof(uint32_t);
case BR_REPLY: {
struct binder_txn *txn = (void*)
if ((end - ptr) * sizeof(uint32_t) & sizeof(struct binder_txn)) {
ALOGE(&parse: reply too small!/n&);
return -1;
binder_dump_txn(txn);
if (bio) {
bio_init_from_txn(bio, txn);
/* todo FREE BUFFER */
ptr += (sizeof(*txn) / sizeof(uint32_t));
//............................
ALOGE(&parse: OOPS %d/n&, cmd);
return -1;
}}int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply){
struct svcinfo *
uint16_t *s;
uint32_t strict_
int allow_
if (txn-&target != svcmgr_handle)
return -1;
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
// s 就是 serviceManager 服务的 discreptor, svcmgr_id =
//uint16_t svcmgr_id[] = {
//&#39;a&#39;,&#39;n&#39;,&#39;d&#39;,&#39;r&#39;,&#39;o&#39;,&#39;i&#39;,&#39;d&#39;,&#39;.&#39;,&#39;o&#39;,&#39;s&#39;,&#39;.&#39;,
//&#39;I&#39;,&#39;S&#39;,&#39;e&#39;,&#39;r&#39;,&#39;v&#39;,&#39;i&#39;,&#39;c&#39;,&#39;e&#39;,&#39;M&#39;,&#39;a&#39;,&#39;n&#39;,&#39;a&#39;,&#39;g&#39;,&#39;e&#39;,&#39;r&#39;
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,&invalid id %s/n&, str8(s));
return -1;
switch(txn-&code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
// 需要查找的 service name
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len, txn-&sender_euid);
bio_put_ref(reply, ptr);
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, ptr, txn-&sender_euid, allow_isolated))
return -1;
case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);
while ((n-- & 0) && si)
bio_put_string16(reply, si-&name);
return -1;
ALOGE(&unknown code %d/n&, txn-&code);
return -1;
bio_put_uint32(reply, 0);
return 0;}1.4 完整的ipc过程
最新教程周点击榜
微信扫一扫

我要回帖

更多关于 bool func int 的文章

 

随机推荐